Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.

Motivation


This case study will introduce the topic of multicolinearity. We will do so by showcasing a real world example where multicolinearity in part resulted in historically contriversial and conflicting findings about the influence of the adoption of right-to-carry (RTC) concealed handgun laws on violent crime rates in the United States.

We will focus on two articles:

  1. The first analysis by Lott and Mustard published in 1996 suggests that RTC laws reduce violent crime. Lott authored a book extending these findings in 1998 called More Guns, Less Crime.

  1. The second analysis is a recent article by Donohue, et al. published in 2017 that suggests that RTC laws increase violent crime. Donohue has also published previous articles with titles such as “Shooting down the”More Guns, Less Crime" Hypothesis

This has been a controversial topic as many other articles also had conflicting results. See here for a list of studies.

The Donohue, et al. article discusses how there are many other important methodolical aspects besides multicolinearity that could account for the historically conflicting results in these previous papers.

In fact, nearly every aspect of the data analysis process was different between the Donohue, et al. analysis and the Lott and Mustard analysis.

However, we will focus particularly on multicolinearity and we will explore how it can influence linear regression analyses and result in different conclusions.

This analysis will demonstrate how methodological details can be critically influential for our overall conclusions and can result in important policy related consequences. This article will provide a basis for the motivation.

John J. Donohue et al., Right‐to‐Carry Laws and Violent Crime: A Comprehensive Assessment Using Panel Data and a State‐Level Synthetic Control Analysis. Journal of Empirical Legal Studies, 16,2 (2019).

David B. Mustard & John Lott. Crime, Deterrence, and Right-to-Carry Concealed Handguns. Coase-Sandor Institute for Law & Economics Working Paper No. 41, (1996).

Here you can see the differences in the data used in the featured RTC articles:

We will perform analyses similar to those in these articles, however we will not try to recreate them, instead we will simplify our analysis to allow us to focus on multicolinearity.

Therefore we will use a subset of the listed explanatory variables and they will be consistent for both analyses that we will perform, with the exception that one analysis will have 6 demographic variables like the analysis in the Donohue, et al. article and the other will have 36 demogrpahic variables like the analysis in the Lott and Mustard article.

Main Question


Our main question:

  1. How does the inclusion of different numbers of age groups influence the results of an analysis of right to carry laws and violence rates?

Learning Objectives


Statistical Learning Objectives:

In this case study, students will learn:
1) what multicolinearity is and how it can influence linear regression coefficients
2) how to look for the presence of multicolinarity
3) the difference between multicolinearity and correlation

Data science Learning Objectives:

  1. joining data from multiple sources (dplyr)
  2. reshaping data into different formats (tidyr)
  3. visualizations (ggplot2)

We will especially focus on using packages and functions from the Tidyverse, such as dplyr and ggplot2. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.

Context


So what exactly is a right-to-carry law?

It is a law thatspecifies if and how citizens are allowed to have a firearm on their person or nearby (for example in the citizen’s car) in public.

The Second Amendment to the United States Constitution guarantees the right to “keep and bear arms”. The amendment was ratified in 1791 as part of the Bill of Rights.

However, there are no federal laws about carrying firearms in public.

These laws are created and enforced at the state level. Sates vary greatly in their laws about the right to carry firearms. Some require extensive effort to obtain a permit to legally carry a firearm, while other states require very minimal effort to legally carry a firearm.

According to Wikipedia about the history of right-to-carry policies in the United States:

Public perception on concealed carry vs open carry has largely flipped. In the early days of the United States, open carrying of firearms, long guns and revolvers was a common and well-accepted practice. Seeing guns carried openly was not considered to be any cause for alarm. Therefore, anyone who would carry a firearm but attempt to conceal it was considered to have something to hide, and presumed to be a criminal. For this reason, concealed carry was denounced as a detestable practice in the early days of the United States.

Concealed weapons bans were passed in Kentucky and Louisiana in 1813. (In those days open carry of weapons for self-defense was considered acceptable; concealed carry was denounced as the practice of criminals.) By 1859, Indiana, Tennessee, Virginia, Alabama, and Ohio had followed suit. By the end of the nineteenth century, similar laws were passed in places such as Texas, Florida, and Oklahoma, which protected some gun rights in their state constitutions. Before the mid 1900s, most U.S. states had passed concealed carry laws rather than banning weapons completely. Until the late 1990s, many Southern states were either “No-Issue” or “Restrictive May-Issue”. Since then, these states have largely enacted “Shall-Issue” licensing laws, with numerous states legalizing “Unrestricted concealed carry”.

See here for more information.

Here are the general categories of Right to Carry Laws:

source

source

You can see that none of the fifty states have no-issue laws currently, meaning that all states allow the right to carry firearms at least in some way, however the level of restrictions is dramatically different from one state to another.

Here you can see how these laws have changed over time around the country:

There is variation from state to state even within the same general category:

For example here are the current carry laws in Idaho which is considered an “Unrestricted - no permit required” state:

Idaho permits the open carrying of firearms.

Idaho law permits both residents and non-residents who are at least 18 years old to carry concealed weapons, without a carry license, outside the limits of or confines of any city, provided the person is not otherwise disqualified from being issued a license to carry.

A person may also carry concealed weapons on or about his or her person, without a license, in the person’s own place of abode or fixed place of business, on property in which the person has any ownership or leasehold interest, or on private property where the person has permission to carry from any person who has an ownership or leasehold interest in that property.

State law also allows any resident of Idaho or a current member of the armed forces of the United States to carry a concealed handgun without a license to carry, provided the person is over 18 years old and not disqualified from being issued a license to carry concealed weapons under state law. An amendment to state law that takes effect on July 1, 2020 changes the reference in the above law from “a resident of Idaho” to “any citizen of the United States.”

And here are the current carry laws in Arizona which is also considered an “Unrestricted- - no permit required” state:

Arizona respects the right of law abiding citizens to openly carry a handgun.

Any person 21 years of age or older, who is not prohibited possessor, may carry a weapon openly or concealed without the need for a license. Any person carrying without a license must acknowledge and comply with the demands of a law enforcement officer when asked if he/she is carrying a concealed deadly weapon, if the officer has initiated an “investigation” such as a traffic stop.

Notice that citizens in Idaho only need to be 18 to carry a firearm, whereas they must be 21 in Arizona.

In contrast here is an example of current carry laws in Maryland which is considered a “Rights Restricted-Very Limited Issue” state:

Carrying and Transportation in Vehicles It is unlawful for any person without a permit to wear or carry a handgun, openly or concealed, upon or about his person. It is also unlawful for any person to knowingly transport a handgun in any vehicle traveling on public roads, highways, waterways or airways, or upon roads or parking lots generally used by the public. This does not apply to any person wearing, carrying or transporting a handgun within the confines of real estate owned or leased by him, or on which he resides, or within the confines of a business establishment owned or leased by him.

Permit To Carry Application for a permit to carry a handgun is made to the Secretary of State Police. In addition to the printed application form, the applicant should submit a notarized letter stating the reasons why he is applying for a permit.

avocado….Right to carry and covid masks?

Limitations


There are some important considerations regarding this data analysis to keep in mind:

  1. We do not use all of the data used by either the Lott and Mustard or Donohue, et al. analyses, nor do we perform the same analysis of each article. We instead perform a much simpler analysis with less variables for the purposes of illustration of the concept of multicollinearity and its influence on regression coefficients, not to reproduce either analysis.

  2. Because our analysis is an oversimplification, our analysis should not be used for determining policy changes, instead we suggest that users consult with a specialist.

We would also like to note that…AVOCADO It is important that we do not treat race as an objective measure. Despite this, it can be used to advance scientific inquiry. For more information on this topic, we have included a link to a paper on the use of race as a measure in epidemiology.

We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
readr to import the CSV file data
[car] to calculate vif values
[purrr] to combine multiple tibbles within a list of tibbles
[forcats] to collapse levels of factors into more summarised versions

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

What are the data?


Below is a table from the Donohue, et al. paper that shows the data used in both analyses, where DAW stands for Donohue, et al. and LM stands for Lott and Mustard.

We will be using a subset of these variables, which are highlighted in green:

Data Import


Demographic and opulation data

To obtain information about age, sex, and race, and overall population we will use US Census Bureau data, just like both of the articles. The cesnus data is available for different time spans. Here are the links for the years used in our analysis. We will use data from 1977 to 2010.

Data Link
years 1977 to 1979 link
years 1980 to 1989 link * county data was used for this decade which also has state information
years 1990 to 1999 link
years 2000 to 2010 link
technical documentation

To import the data we will use the read_csv() function of the readr package for the csv files. In some decades, there are separate files for each year, we will read each of these together using the base list.files() function to get all of the names for each file and then the map() function of the purrr package to apply the read_csv() function on all of the file paths in the list created by list.files(). For years that are txt files we will use read_table2() also fo the readr package. The read_table2() function, unlike the read_table(), allows for any number of whitespace characters between columns, and the lines can be of different lengths.

AVOCADO I am a bit confused about the last decade… it’s only one file but it seems to need map…

[[1]]
# A tibble: 62,244 x 21
   REGION DIVISION STATE NAME    SEX ORIGIN  RACE AGEGRP ESTIMATESBASE20…
    <dbl>    <dbl> <dbl> <chr> <dbl>  <dbl> <dbl>  <dbl>            <dbl>
 1      0        0     0 Unit…     0      0     0      0        281424600
 2      0        0     0 Unit…     0      0     0      1         19176154
 3      0        0     0 Unit…     0      0     0      2         20549855
 4      0        0     0 Unit…     0      0     0      3         20528425
 5      0        0     0 Unit…     0      0     0      4         20218782
 6      0        0     0 Unit…     0      0     0      5         18962964
 7      0        0     0 Unit…     0      0     0      6         19381792
 8      0        0     0 Unit…     0      0     0      7         20511067
 9      0        0     0 Unit…     0      0     0      8         22707390
10      0        0     0 Unit…     0      0     0      9         22442442
# … with 62,234 more rows, and 12 more variables: POPESTIMATE2000 <dbl>,
#   POPESTIMATE2001 <dbl>, POPESTIMATE2002 <dbl>, POPESTIMATE2003 <dbl>,
#   POPESTIMATE2004 <dbl>, POPESTIMATE2005 <dbl>, POPESTIMATE2006 <dbl>,
#   POPESTIMATE2007 <dbl>, POPESTIMATE2008 <dbl>, POPESTIMATE2009 <dbl>,
#   CENSUS2010POP <dbl>, POPESTIMATE2010 <dbl>

Notice that the STATE variable for the demographic data is numeric. That is because it is encoded by Federal Information Processing Standard (FIPS) state codes{target="_blank". Thus we also need to import data about FIPS encoding so that we can identify what data corresponds to what state.

State FIPS codes

The following data was downloaded from the US Census Bureau.

To import the data we will use the read_xls() function of the readxl package. Since the first five lines of this excel is information about the source of the data and when it was released, we need to skip importing these lines using the skip argument so that the data has the same number of columns for each row.

# A tibble: 64 x 4
   Region Division `State\n(FIPS)` Name                    
   <chr>  <chr>    <chr>           <chr>                   
 1 1      0        00              Northeast Region        
 2 1      1        00              New England Division    
 3 1      1        09              Connecticut             
 4 1      1        23              Maine                   
 5 1      1        25              Massachusetts           
 6 1      1        33              New Hampshire           
 7 1      1        44              Rhode Island            
 8 1      1        50              Vermont                 
 9 1      2        00              Middle Atlantic Division
10 1      2        34              New Jersey              
# … with 54 more rows

Police staffing data

The following data was downloaded from the Federal Bureau of Investigation.

The read_csv() function of the readr package guesses what the class is for each variable, but sometimes it makes mistakes. It is good to specify the class for variables if you know them. We know that we want the variables about male and female counts to be numeric. We can specify that using the col_types = argument. See here and here for more information.

# A tibble: 6 x 21
  data_year ori   pub_agency_name pub_agency_unit state_abbr division_name
      <dbl> <chr> <chr>           <chr>           <chr>      <chr>        
1      1960 AK02… Alcohol Bevera… <NA>            AK         Pacific      
2      1960 AL00… Homewood        <NA>            AL         East South C…
3      1960 AL01… Coffeeville     <NA>            AL         East South C…
4      1960 AL01… Coffee          <NA>            AL         East South C…
5      1960 AL02… Mentone         <NA>            AL         East South C…
6      1960 AL03… Greensboro      <NA>            AL         East South C…
# … with 15 more variables: region_name <chr>, county_name <chr>,
#   agency_type_name <chr>, population_group_desc <chr>, population <dbl>,
#   male_officer_ct <dbl>, male_civilian_ct <dbl>, male_total_ct <dbl>,
#   female_officer_ct <lgl>, female_civilian_ct <lgl>, female_total_ct <dbl>,
#   officer_ct <lgl>, civilian_ct <lgl>, total_pe_ct <lgl>,
#   pe_ct_per_1000 <lgl>

Unemplyment data

The following data was downloaded from the U.S. Bureau of Labor Statistics.

There are excel files for each state. As you can see, there are many rows to skip to make sure that there are the same number of columns for each row. We can also see that the state name is located in a couple of the first rows.

We can also see that here if we just try to read in the files directly.

[[1]]
# A tibble: 55 x 14
   `Local Area Une… ...2  ...3  ...4  ...5  ...6  ...7  ...8  ...9  ...10 ...11
   <chr>            <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
 1 Original Data V… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 2 <NA>             <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 3 Series Id:       LAUS… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 4 Not Seasonally … <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 5 Area:            Alab… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 6 Area Type:       Stat… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 7 State/Region/Di… Alab… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 8 Measure:         unem… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
 9 Years:           1977… <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
10 <NA>             <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>  <NA> 
# … with 45 more rows, and 3 more variables: ...12 <chr>, ...13 <chr>,
#   ...14 <chr>

So now we will skip the first 10 lines. And also create a names tibble that contains only the cell with the state information.

[[1]]
# A tibble: 44 x 14
    Year   Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov   Dec
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  1977   7.5   9     7.7   7.2   6.8   8.6   8     7.8   6.7   6.3   6.3   6  
 2  1978   7.1   6.9   6.2   5.4   5.1   6.9   6.7   6.7   6.5   6.3   6.3   6.5
 3  1979   6.7   7.5   6.9   6.6   6.4   8.4   7.7   7.8   7.1   7.2   6.9   6.7
 4  1980   7.7   7.8   7.4   7.4   8.4   9.7  10.4  10.3   9.3   9.6   9.4   9  
 5  1981  10    10.3   9.5   9.1   9.4  11.1  10.4  10.9  10.8  11.7  11.5  11.8
 6  1982  13.2  13.2  12.9  12.6  12.8  14.5  14.7  14.8  14.7  15.1  15.4  15.3
 7  1983  16    16    14.5  13.7  13.3  14.6  13.9  13.8  13.2  12.8  12.1  11.8
 8  1984  12.5  12.4  11.4  10.8  10.1  11.3  11.5  11.3  10.8  10.2   9.7  10.1
 9  1985  10.7  10.5   9.8   8.7   8.4   9.6   9.2   8.8   8.6   8.6   8.4   8.7
10  1986   9.3  10.4  10.1   9.4   9.4  10.5   9.7   9.6   9.7   9.7   9.6   9  
# … with 34 more rows, and 1 more variable: Annual <dbl>

To get the state name for each file using the map() function to perform functions across all of the files, we will specifically import only a small range of cells using the range = argument and then grab the cell that has state information based on it’s location within the range of cells imported using c() and then use the base unlist() function to unlist the list that this creates.

 [1] "Alabama"              "Alaska"               "Arizona"             
 [4] "Arkansas"             "California"           "Colorado"            
 [7] "Connecticut"          "Delaware"             "District of Columbia"
[10] "Florida"              "Georgia"              "Hawaii"              
[13] "Idaho"                "Illinois"             "Indiana"             
[16] "Iowa"                 "Kansas"               "Kentucky"            
[19] "Louisiana"            "Maine"                "Maryland"            
[22] "Massachusetts"        "Michigan"             "Minnesota"           
[25] "Mississippi"          "Missouri"             "Montana"             
[28] "Nebraska"             "Nevada"               "New Hampshire"       
[31] "New Jersey"           "New Mexico"           "New York"            
[34] "North Carolina"       "North Dakota"         "Ohio"                
[37] "Oklahoma"             "Oregon"               "Pennsylvania"        
[40] "Rhode Island"         "South Carolina"       "South Dakota"        
[43] "Tennessee"            "Texas"                "Utah"                
[46] "Vermont"              "Virginia"             "Washington"          
[49] "West Virginia"        "Wisconsin"            "Wyoming"             

Now we will make these values the names of the different tibbles within ue_rate_data.

Poverty data

Extracted from Table 21 from US Census Bureau Poverty Data

AVOCado strange issue

# A tibble: 6 x 6
  `NOTE: Number in thousa… ...2  ...3   ...4         ...5         ...6          
  <chr>                    <chr> <chr>  <chr>        <chr>        <chr>         
1 2018                     <NA>  <NA>    <NA>        <NA>          <NA>         
2 STATE                    Total Number "Standard\n… Percent      "Standard\ner…
3 Alabama                  4877  779    "65"         16           "1.3"         
4 Alaska                   720   94     "9"          13.1         "1.2"         
5 Arizona                  7241  929    "80"         12.80000000… "1.1000000000…
6 Arkansas                 2912  462    "38"         15.9         "1.3"         

We can see that this will require some wranlging to make the data more usable.

Violent crime

Violent crime data was obtained from here This data is a bit trickier because of spaces and / in the column names, thus the read_lines() function of the readr package works better than the read_csv() function.

[1] "Estimated crime in Alabama"                                                                                                           
[2] "\n,,National or state crime,,,,,,,"                                                                                                   
[3] "\n,,Violent crime,,,,,,,"                                                                                                             
[4] "\nYear,Population,Violent crime total,Murder and nonnegligent Manslaughter,Legacy rape /1,Revised rape /2,Robbery,Aggravated assault,"
[5] "1977,   3690000,      15293,         524,         929,,       3572,      10268 "                                                      
[6] "1978,   3742000,      15682,         499,         954,,       3708,      10521 "                                                      

We can see that this data will also require some wranlging to make it more usable.

Right-to-carry data

This data is extracted from table in Donohue paper {target="_blank"}. We will use the function pdf_text() of the pdftools package to import the pdf document.

[1] "                                NBER WORKING PAPER SERIES\n                      RIGHT-TO-CARRY LAWS AND VIOLENT CRIME:\n              A COMPREHENSIVE ASSESSMENT USING PANEL DATA AND\n                    A STATE-LEVEL SYNTHETIC CONTROL ANALYSIS\n                                          John J. Donohue\n                                            Abhay Aneja\n                                           Kyle D. Weber\n                                         Working Paper 23510\n                                 http://www.nber.org/papers/w23510\n                      NATIONAL BUREAU OF ECONOMIC RESEARCH\n                                     1050 Massachusetts Avenue\n                                        Cambridge, MA 02138\n                                 June 2017, Revised November 2018\nPreviously circulated as \"Right-to-Carry Laws and Violent Crime: A Comprehensive Assessment\nUsing Panel Data and a State-Level Synthetic Controls Analysis.\" We thank Dan Ho, Stefano\nDellaVigna, Rob Tibshirani, Trevor Hastie, StefanWager, Jeff Strnad, and participants at the\n2011 Conference of Empirical Legal Studies (CELS), 2012 American Law and Economics\nAssociation (ALEA) Annual Meeting, 2013 Canadian Law and Economics Association (CLEA)\nAnnual Meeting, 2015 NBER Summer Institute (Crime), and the Stanford Law School faculty\nworkshop for their comments and helpful suggestions. Financial support was provided by\nStanford Law School. We are indebted to Alberto Abadie, Alexis Diamond, and Jens\nHainmueller for their work developing the synthetic control algorithm and programming the Stata\nmodule used in this paper and for their helpful comments. The authors would also like to thank\nAlex Albright, Andrew Baker, Jacob Dorn, Bhargav Gopal, Crystal Huang, Mira Korb, Haksoo\nLee, Isaac Rabbani, Akshay Rao, Vikram Rao, Henrik Sachs and Sidharth Sah who provided\nexcellent research assistance, as well as Addis O’Connor and Alex Chekholko at the Research\nComputing division of Stanford’s Information Technology Services for their technical support.\nThe views expressed herein are those of the author and do not necessarily reflect the views of the\nNational Bureau of Economic Research.\nNBER working papers are circulated for discussion and comment purposes. They have not been\npeer-reviewed or been subject to the review by the NBER Board of Directors that accompanies\nofficial NBER publications.\n© 2017 by John J. Donohue, Abhay Aneja, and Kyle D. Weber. All rights reserved. Short\nsections of text, not to exceed two paragraphs, may be quoted without explicit permission\nprovided that full credit, including © notice, is given to the source.\n"

Again, this data will also require quite a bit of wrangling.

Data Wrangling


State FIPS codes

Let’s first take a look at our state FIPS data to see if it needs any cleaning or reshaping. We should start with this data, becuase we will need to use it to wrangle some of the other data.

# A tibble: 6 x 4
  Region Division `State\n(FIPS)` Name                
  <chr>  <chr>    <chr>           <chr>               
1 1      0        00              Northeast Region    
2 1      1        00              New England Division
3 1      1        09              Connecticut         
4 1      1        23              Maine               
5 1      1        25              Massachusetts       
6 1      1        33              New Hampshire       

We only need the last two columns, but we might want to rename them. The Name variable is vague. The variable with the FIPS code is called State\n(FIPS). To get rid of the new line in this variable name and to change the Name variable to something more informative, we will use the rename() function of the dplyr package. To use this function, we need to list the new name first followed by = and then the existing variable. We can rename multiple variables at the same time by using a comma to separate the variables we are renaming. We will use the select() function also of the dplyr package just to keep these variables, and we will filter out the rows with FIPS values of 00 with the filter() function, agian also part of the dplyr package. we will specify that we want STATEFP values that are not equal to 00 by using this operator: !=. We will also use the double pipe operator %<>% of the magrittr package which allows us to use data as iuput and then reassign it after we peform sum functions using it.

# A tibble: 51 x 2
   STATEFP STATE        
   <chr>   <chr>        
 1 09      Connecticut  
 2 23      Maine        
 3 25      Massachusetts
 4 33      New Hampshire
 5 44      Rhode Island 
 6 50      Vermont      
 7 34      New Jersey   
 8 36      New York     
 9 42      Pennsylvania 
10 17      Illinois     
# … with 41 more rows

Demographic and population data

Click here to see detailed information about how the demogrphic data was wrangled

1977-1979


Now let’s take a look at our demographic data across the decades that we wish to study. If you have very wide data (meaning it has many columns), one way to view the data so that you can see all of the columns at the same time is to use the glimpse() function of the dplyr package.

Taking a look at the first decade of data, we can see that the Race/Sex Indicator contains two types of data, the race and the sex. This does not follow the tidy data philosophy, where each cell of a tibble should only contain one piece of information. Typically one might think of using the separate() function of the tidyr package to split this variable into two. However, one of the race values is Other races and since this also has a space, this makes separating this data more tricky.

Instead we will use the str_extract() function of the stringr package and the mutate() function of the dplyr package. The “mutate()” will allow us to create new variables, and “str_extract()” function will allow us to match specific patterns and pull out matches to those patterns. Therefore, if the Race/Sex Indicator value is Other races male and if we extract patterns matching either "male" or "female" which we can specify like this pattern = "male|female" then, the value will be male.

First we need to rename the Race/Sex Indicator varaible to not have spaces so that it is compatible with the str_extract() function.

We also want to rename a couple of variables to be simpler and filter the data to only include the years of the data we are interested in, as well as remove some variables that we dont need like the FIPS State Code. We can remove variables by using the select() function with a - minus sign in front of the variable we wish to remove.

Rows: 3,060
Columns: 22
$ `Year of Estimate`   <dbl> 1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970, …
$ `FIPS State Code`    <chr> "01", "01", "01", "01", "01", "01", "02", "02", …
$ `State Name`         <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Ala…
$ `Race/Sex Indicator` <chr> "White male", "White female", "Black male", "Bla…
$ `Under 5 years`      <dbl> 105856, 100613, 47403, 47079, 244, 250, 12382, 1…
$ `5 to 9 years`       <dbl> 120876, 115194, 55443, 54851, 255, 251, 13888, 1…
$ `10 to 14 years`     <dbl> 129091, 122352, 60427, 60065, 253, 245, 13255, 1…
$ `15 to 19 years`     <dbl> 119500, 116107, 52921, 55144, 281, 254, 11179, 9…
$ `20 to 24 years`     <dbl> 103665, 108513, 29948, 35165, 413, 331, 20237, 1…
$ `25 to 29 years`     <dbl> 86538, 88359, 19535, 23662, 239, 302, 12538, 107…
$ `30 to 34 years`     <dbl> 74452, 77595, 17196, 22021, 236, 284, 10331, 865…
$ `35 to 39 years`     <dbl> 71511, 74941, 16654, 22248, 161, 279, 9548, 7510…
$ `40 to 44 years`     <dbl> 75242, 78908, 17564, 24249, 127, 253, 8282, 6353…
$ `45 to 49 years`     <dbl> 73874, 78589, 18186, 23028, 108, 148, 6995, 5820…
$ `50 to 54 years`     <dbl> 68048, 72481, 17618, 22104, 95, 100, 5609, 4494,…
$ `55 to 59 years`     <dbl> 61071, 67699, 18118, 21909, 88, 93, 4029, 2986, …
$ `60 to 64 years`     <dbl> 52361, 61065, 16456, 20068, 69, 94, 2392, 1830, …
$ `65 to 69 years`     <dbl> 38977, 49685, 14498, 19364, 54, 73, 1292, 965, 2…
$ `70 to 74 years`     <dbl> 26767, 37227, 9541, 12509, 70, 66, 602, 496, 8, …
$ `75 to 79 years`     <dbl> 17504, 27163, 6030, 8291, 31, 52, 326, 305, 1, 5…
$ `80 to 84 years`     <dbl> 9937, 16470, 3485, 5031, 37, 30, 211, 186, 4, 5,…
$ `85 years and over`  <dbl> 5616, 10445, 2448, 4035, 76, 29, 143, 126, 19, 4…
Rows: 918
Columns: 22
$ YEAR                <dbl> 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1…
$ STATE               <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Alab…
$ `Under 5 years`     <dbl> 98814, 94595, 46201, 45784, 590, 621, 14316, 1353…
$ `5 to 9 years`      <dbl> 113365, 107395, 50097, 49329, 672, 660, 14621, 13…
$ `10 to 14 years`    <dbl> 123107, 116182, 54925, 53955, 677, 653, 14795, 13…
$ `15 to 19 years`    <dbl> 135343, 130433, 58468, 59926, 674, 605, 15207, 13…
$ `20 to 24 years`    <dbl> 126053, 125352, 43898, 51433, 722, 773, 20106, 16…
$ `25 to 29 years`    <dbl> 111547, 112471, 31014, 36648, 638, 835, 20444, 18…
$ `30 to 34 years`    <dbl> 100674, 101543, 22528, 26694, 571, 766, 17514, 15…
$ `35 to 39 years`    <dbl> 81038, 83369, 17473, 22213, 498, 586, 13098, 1069…
$ `40 to 44 years`    <dbl> 75042, 77793, 16446, 22146, 356, 479, 10067, 7935…
$ `45 to 49 years`    <dbl> 76296, 79753, 16578, 22576, 295, 432, 8460, 6848,…
$ `50 to 54 years`    <dbl> 74844, 81079, 17117, 23028, 206, 326, 7268, 5914,…
$ `55 to 59 years`    <dbl> 67785, 75905, 16437, 21435, 166, 213, 5398, 4485,…
$ `60 to 64 years`    <dbl> 58853, 69406, 16276, 21075, 145, 174, 3349, 2708,…
$ `65 to 69 years`    <dbl> 48848, 62430, 15837, 21126, 107, 173, 1714, 1468,…
$ `70 to 74 years`    <dbl> 34475, 50075, 11450, 16028, 90, 138, 915, 928, 22…
$ `75 to 79 years`    <dbl> 20977, 34027, 7601, 10825, 53, 106, 500, 493, 10,…
$ `80 to 84 years`    <dbl> 10831, 21483, 3896, 6272, 25, 49, 237, 268, 4, 7,…
$ `85 years and over` <dbl> 6683, 15729, 2667, 5426, 33, 41, 153, 211, 11, 6,…
$ SEX                 <chr> "male", "female", "male", "female", "male", "fema…
$ RACE                <chr> "White", "White", "Black", "Black", "Other", "Oth…

That’s looking pretty good! We also want to take all the age group variabels and make one variable that is the age group name and one that is the value of the population count for that age group. To do this we will use the pivot_longer() function of the tidyr package. To use this function, we need to use the cols argument to indicate which columns we want to pivot. We also name the new variables we will create with the names_to and values_to arguments. The names_to will be the name of the variable that will identify each age group and values_to will be the name of the variable that contains the corresponding population values.

Rows: 16,524
Columns: 6
$ YEAR      <dbl> 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977,…
$ STATE     <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Alabama", "Ala…
$ SEX       <chr> "male", "male", "male", "male", "male", "male", "male", "ma…
$ RACE      <chr> "White", "White", "White", "White", "White", "White", "Whit…
$ AGE_GROUP <chr> "Under 5 years", "5 to 9 years", "10 to 14 years", "15 to 1…
$ SUB_POP   <dbl> 98814, 113365, 123107, 135343, 126053, 111547, 100674, 8103…

We also want to get data about the total population for the state for each year.

To do so we can sum all the values for the SUB_POP variable that we just created. To do this we can use the group_by and summarise() functions of the dplyr package. The group_by() function specifies how we want to calculate our sum, that we would like to calculate it for each year and each state individually. Thus, all the values that have the same STATE and YEAR values will be summed together, rather than summing using all of the values in the SUB_POP variable. The .groups argument allows us to remove the grouping after we peform the calculation with summarise().

# A tibble: 153 x 3
    YEAR STATE                 TOT_POP
   <dbl> <chr>                   <dbl>
 1  1977 Alabama               3782571
 2  1977 Alaska                 397220
 3  1977 Arizona               2427296
 4  1977 Arkansas              2207195
 5  1977 California           22350332
 6  1977 Colorado              2696179
 7  1977 Connecticut           3088745
 8  1977 Delaware               594815
 9  1977 District of Columbia   681766
10  1977 Florida               8888806
# … with 143 more rows

Now we will add the population value to the demographic tibble using the left_join() function of the dplyr package. It is imporant that we specify how this should be done, that the YEAR and STATE variable vlaues should match eachother. This will place the dem_77_79 variables to the left of the pop_77_79 data.

# A tibble: 16,524 x 7
    YEAR STATE   SEX   RACE  AGE_GROUP      SUB_POP TOT_POP
   <dbl> <chr>   <chr> <chr> <chr>            <dbl>   <dbl>
 1  1977 Alabama male  White Under 5 years    98814 3782571
 2  1977 Alabama male  White 5 to 9 years    113365 3782571
 3  1977 Alabama male  White 10 to 14 years  123107 3782571
 4  1977 Alabama male  White 15 to 19 years  135343 3782571
 5  1977 Alabama male  White 20 to 24 years  126053 3782571
 6  1977 Alabama male  White 25 to 29 years  111547 3782571
 7  1977 Alabama male  White 30 to 34 years  100674 3782571
 8  1977 Alabama male  White 35 to 39 years   81038 3782571
 9  1977 Alabama male  White 40 to 44 years   75042 3782571
10  1977 Alabama male  White 45 to 49 years   76296 3782571
# … with 16,514 more rows

We will also calculate the percentage that each group makes up of the total population, by dividing the SUB_POP by the TOT_POP and multiplying by 100 using the mutate() function. we will also remove the other population variables.

# A tibble: 16,524 x 6
    YEAR STATE   SEX   RACE  AGE_GROUP      PERC_SUB_POP
   <dbl> <chr>   <chr> <chr> <chr>                 <dbl>
 1  1977 Alabama male  White Under 5 years          2.61
 2  1977 Alabama male  White 5 to 9 years           3.00
 3  1977 Alabama male  White 10 to 14 years         3.25
 4  1977 Alabama male  White 15 to 19 years         3.58
 5  1977 Alabama male  White 20 to 24 years         3.33
 6  1977 Alabama male  White 25 to 29 years         2.95
 7  1977 Alabama male  White 30 to 34 years         2.66
 8  1977 Alabama male  White 35 to 39 years         2.14
 9  1977 Alabama male  White 40 to 44 years         1.98
10  1977 Alabama male  White 45 to 49 years         2.02
# … with 16,514 more rows

It is important to make sure that we have the total values we would expect. We have two levels of SEX, three levels of Race, three levels of YEAR, eighteen levels of AGE_GROUP, and fifty one levels of STATE. If we multiply this together we get 16,524 which is the same as the number of rows in our final dem_77_79 data. Looks good!

Also Let’s make the values of the SEX variable capatalized so that they match the other values of the other variables like RACE etc. This will help us to keep consistent values across the different years as we wrangle the data for the other decades. To do so we will use the str_to_title() function of the stringr package. We need to use the pull() function to get the values of SEX out of dem_77_79. Once we make them captialized they are then reasigned to the SEX variable.

1980-1989


For this decade each year is a separate tibble and they are combined as a list.

[1] "list"

So the first thing we need to do is combine each tibble of the list together. We can do that using the bind_rows() function of dplyr which appends the data together based on the presence of columns with the same name in the different tibbles. We will use the map_df() function of the purrr package to allow us to do this across each tibble in our list.

Rows: 188,460
Columns: 21
$ `Year of Estimate`            <dbl> 1980, 1980, 1980, 1980, 1980, 1980, 198…
$ `FIPS State and County Codes` <chr> "01001", "01001", "01001", "01001", "01…
$ `Race/Sex Indicator`          <chr> "White male", "White female", "Black ma…
$ `Under 5 years`               <dbl> 985, 831, 357, 346, 4, 7, 2422, 2346, 6…
$ `5 to 9 years`                <dbl> 1096, 987, 427, 395, 9, 8, 2661, 2467, …
$ `10 to 14 years`              <dbl> 1271, 1074, 395, 415, 4, 11, 2783, 2614…
$ `15 to 19 years`              <dbl> 1308, 1259, 460, 429, 10, 5, 3049, 2841…
$ `20 to 24 years`              <dbl> 972, 1006, 300, 380, 3, 3, 2423, 2428, …
$ `25 to 29 years`              <dbl> 850, 912, 240, 235, 2, 11, 2372, 2475, …
$ `30 to 34 years`              <dbl> 891, 983, 163, 196, 4, 10, 2410, 2400, …
$ `35 to 39 years`              <dbl> 942, 1015, 120, 158, 3, 12, 2101, 2202,…
$ `40 to 44 years`              <dbl> 854, 882, 133, 147, 2, 11, 1881, 1859, …
$ `45 to 49 years`              <dbl> 828, 739, 107, 154, 4, 11, 1708, 1694, …
$ `50 to 54 years`              <dbl> 631, 602, 113, 165, 1, 7, 1657, 1798, 2…
$ `55 to 59 years`              <dbl> 524, 532, 113, 150, 1, 2, 1641, 1943, 1…
$ `60 to 64 years`              <dbl> 428, 451, 126, 166, 0, 1, 1630, 1819, 1…
$ `65 to 69 years`              <dbl> 358, 417, 128, 160, 1, 0, 1503, 1729, 1…
$ `70 to 74 years`              <dbl> 242, 332, 87, 119, 0, 0, 1163, 1335, 16…
$ `75 to 79 years`              <dbl> 123, 237, 70, 94, 0, 0, 671, 906, 87, 1…
$ `80 to 84 years`              <dbl> 52, 137, 31, 57, 0, 0, 331, 527, 43, 67…
$ `85 years and over`           <dbl> 39, 86, 13, 44, 0, 1, 187, 408, 27, 65,…

Great! Now our data is all together.

Now we will wrangle the data similarly to the previous decade.

Rows: 188,460
Columns: 22
$ YEAR                          <dbl> 1980, 1980, 1980, 1980, 1980, 1980, 198…
$ `FIPS State and County Codes` <chr> "01001", "01001", "01001", "01001", "01…
$ `Under 5 years`               <dbl> 985, 831, 357, 346, 4, 7, 2422, 2346, 6…
$ `5 to 9 years`                <dbl> 1096, 987, 427, 395, 9, 8, 2661, 2467, …
$ `10 to 14 years`              <dbl> 1271, 1074, 395, 415, 4, 11, 2783, 2614…
$ `15 to 19 years`              <dbl> 1308, 1259, 460, 429, 10, 5, 3049, 2841…
$ `20 to 24 years`              <dbl> 972, 1006, 300, 380, 3, 3, 2423, 2428, …
$ `25 to 29 years`              <dbl> 850, 912, 240, 235, 2, 11, 2372, 2475, …
$ `30 to 34 years`              <dbl> 891, 983, 163, 196, 4, 10, 2410, 2400, …
$ `35 to 39 years`              <dbl> 942, 1015, 120, 158, 3, 12, 2101, 2202,…
$ `40 to 44 years`              <dbl> 854, 882, 133, 147, 2, 11, 1881, 1859, …
$ `45 to 49 years`              <dbl> 828, 739, 107, 154, 4, 11, 1708, 1694, …
$ `50 to 54 years`              <dbl> 631, 602, 113, 165, 1, 7, 1657, 1798, 2…
$ `55 to 59 years`              <dbl> 524, 532, 113, 150, 1, 2, 1641, 1943, 1…
$ `60 to 64 years`              <dbl> 428, 451, 126, 166, 0, 1, 1630, 1819, 1…
$ `65 to 69 years`              <dbl> 358, 417, 128, 160, 1, 0, 1503, 1729, 1…
$ `70 to 74 years`              <dbl> 242, 332, 87, 119, 0, 0, 1163, 1335, 16…
$ `75 to 79 years`              <dbl> 123, 237, 70, 94, 0, 0, 671, 906, 87, 1…
$ `80 to 84 years`              <dbl> 52, 137, 31, 57, 0, 0, 331, 527, 43, 67…
$ `85 years and over`           <dbl> 39, 86, 13, 44, 0, 1, 187, 408, 27, 65,…
$ SEX                           <chr> "male", "female", "male", "female", "ma…
$ RACE                          <chr> "White", "White", "Black", "Black", "Ot…

Notice that this time the state information is based on the numeric FIPS value. We want only the first two values, as the rest indicate the county. We can use the str_sub() function of the stringr package for this. We will specify that we want to start at the first position and end at the second. Just like str_extract() we need to rename this variable first so that it is compatible.

Rows: 188,460
Columns: 23
$ YEAR                <dbl> 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1…
$ STATEFP_temp        <chr> "01001", "01001", "01001", "01001", "01001", "010…
$ `Under 5 years`     <dbl> 985, 831, 357, 346, 4, 7, 2422, 2346, 672, 645, 3…
$ `5 to 9 years`      <dbl> 1096, 987, 427, 395, 9, 8, 2661, 2467, 740, 680, …
$ `10 to 14 years`    <dbl> 1271, 1074, 395, 415, 4, 11, 2783, 2614, 644, 670…
$ `15 to 19 years`    <dbl> 1308, 1259, 460, 429, 10, 5, 3049, 2841, 711, 762…
$ `20 to 24 years`    <dbl> 972, 1006, 300, 380, 3, 3, 2423, 2428, 516, 601, …
$ `25 to 29 years`    <dbl> 850, 912, 240, 235, 2, 11, 2372, 2475, 414, 469, …
$ `30 to 34 years`    <dbl> 891, 983, 163, 196, 4, 10, 2410, 2400, 303, 352, …
$ `35 to 39 years`    <dbl> 942, 1015, 120, 158, 3, 12, 2101, 2202, 224, 260,…
$ `40 to 44 years`    <dbl> 854, 882, 133, 147, 2, 11, 1881, 1859, 206, 288, …
$ `45 to 49 years`    <dbl> 828, 739, 107, 154, 4, 11, 1708, 1694, 219, 236, …
$ `50 to 54 years`    <dbl> 631, 602, 113, 165, 1, 7, 1657, 1798, 203, 261, 7…
$ `55 to 59 years`    <dbl> 524, 532, 113, 150, 1, 2, 1641, 1943, 178, 219, 8…
$ `60 to 64 years`    <dbl> 428, 451, 126, 166, 0, 1, 1630, 1819, 171, 209, 8…
$ `65 to 69 years`    <dbl> 358, 417, 128, 160, 1, 0, 1503, 1729, 170, 232, 6…
$ `70 to 74 years`    <dbl> 242, 332, 87, 119, 0, 0, 1163, 1335, 164, 182, 4,…
$ `75 to 79 years`    <dbl> 123, 237, 70, 94, 0, 0, 671, 906, 87, 129, 3, 6, …
$ `80 to 84 years`    <dbl> 52, 137, 31, 57, 0, 0, 331, 527, 43, 67, 1, 2, 56…
$ `85 years and over` <dbl> 39, 86, 13, 44, 0, 1, 187, 408, 27, 65, 1, 1, 30,…
$ SEX                 <chr> "male", "female", "male", "female", "male", "fema…
$ RACE                <chr> "White", "White", "Black", "Black", "Other", "Oth…
$ STATE               <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Alab…
# A tibble: 55,080 x 6
    YEAR STATE   AGE_GROUP      SEX    RACE  SUB_POP
   <dbl> <chr>   <chr>          <chr>  <chr>   <dbl>
 1  1980 Alabama 10 to 14 years female Black   50108
 2  1980 Alabama 10 to 14 years female Other     805
 3  1980 Alabama 10 to 14 years female White  109066
 4  1980 Alabama 10 to 14 years male   Black   50768
 5  1980 Alabama 10 to 14 years male   Other     826
 6  1980 Alabama 10 to 14 years male   White  115988
 7  1980 Alabama 15 to 19 years female Black   58428
 8  1980 Alabama 15 to 19 years female Other     743
 9  1980 Alabama 15 to 19 years female White  126783
10  1980 Alabama 15 to 19 years male   Black   56808
# … with 55,070 more rows
# A tibble: 55,080 x 6
    YEAR STATE   AGE_GROUP      SEX    RACE  PERC_SUB_POP
   <dbl> <chr>   <chr>          <chr>  <chr>        <dbl>
 1  1980 Alabama 10 to 14 years female Black       1.28  
 2  1980 Alabama 10 to 14 years female Other       0.0206
 3  1980 Alabama 10 to 14 years female White       2.80  
 4  1980 Alabama 10 to 14 years male   Black       1.30  
 5  1980 Alabama 10 to 14 years male   Other       0.0212
 6  1980 Alabama 10 to 14 years male   White       2.97  
 7  1980 Alabama 15 to 19 years female Black       1.50  
 8  1980 Alabama 15 to 19 years female Other       0.0191
 9  1980 Alabama 15 to 19 years female White       3.25  
10  1980 Alabama 15 to 19 years male   Black       1.46  
# … with 55,070 more rows

Just like with the data from the 70s we will also change the values for SEX to be capitalized.

Again, it is important to make sure that we have the total values we would expect. This time we have: two levels of SEX, three levels of Race, ten levels of YEAR, eighteen levels of AGE_GROUP, and fifty one levels of STATE.

If we multiply these together we get 55,080, which is the same as the number of rows of the final dem_80_89 data. Looks good!

1990-1999


Just like the 80s we need to combine the data across the files:

Rows: 43,870
Columns: 19
$ Year     <dbl> NA, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 19…
$ e        <chr> NA, "01", "01", "01", "01", "01", "01", "01", "01", "01", "0…
$ Age      <dbl> NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16…
$ Male     <dbl> NA, 20406, 19393, 18990, 19246, 19502, 19560, 19091, 19605, …
$ Female   <dbl> NA, 19101, 18114, 18043, 17786, 18366, 18386, 18047, 18316, …
$ Male_1   <dbl> NA, 9794, 9475, 9097, 9002, 9076, 9169, 8919, 9219, 9247, 10…
$ Female_1 <dbl> NA, 9414, 9247, 8837, 8701, 8989, 9093, 8736, 9192, 9108, 97…
$ Male_2   <dbl> NA, 103, 87, 97, 94, 108, 128, 160, 178, 166, 205, 194, 179,…
$ Female_2 <dbl> NA, 90, 93, 100, 115, 114, 130, 134, 162, 155, 193, 185, 202…
$ Male_3   <dbl> NA, 192, 146, 175, 150, 168, 170, 183, 171, 136, 177, 169, 1…
$ Female_3 <dbl> NA, 170, 182, 160, 157, 178, 158, 173, 177, 185, 179, 171, 1…
$ Male_4   <dbl> NA, 223, 190, 198, 186, 190, 210, 188, 178, 182, 221, 194, 1…
$ Female_4 <dbl> NA, 220, 196, 173, 191, 190, 170, 172, 179, 173, 166, 175, 1…
$ Male_5   <dbl> NA, 47, 41, 32, 35, 36, 30, 28, 27, 29, 32, 31, 33, 34, 32, …
$ Female_5 <dbl> NA, 45, 47, 41, 30, 26, 37, 23, 35, 31, 28, 38, 22, 39, 29, …
$ Male_6   <dbl> NA, 1, 2, 1, 9, 5, 8, 2, 4, 6, 6, 0, 1, 9, 6, 7, 5, 2, 2, 4,…
$ Female_6 <dbl> NA, 8, 0, 2, 1, 4, 5, 3, 4, 4, 3, 4, 2, 2, 7, 0, 2, 2, 1, 6,…
$ Male_7   <dbl> NA, 5, 7, 2, 3, 5, 11, 2, 7, 12, 10, 7, 5, 6, 5, 6, 6, 2, 11…
$ Female_7 <dbl> NA, 5, 5, 5, 3, 14, 6, 7, 6, 3, 11, 5, 5, 7, 8, 6, 6, 7, 3, …

For this decade the column names can’t all be imported in a simple way from the table, so they need to be recoded.

Here is what the data looks like before importing:

So, first using the base colnames() function we change the names of the column names.

Rows: 43,870
Columns: 19
$ YEAR      <dbl> NA, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1…
$ STATEFP   <chr> NA, "01", "01", "01", "01", "01", "01", "01", "01", "01", "…
$ Age       <dbl> NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1…
$ NH_W_M    <dbl> NA, 20406, 19393, 18990, 19246, 19502, 19560, 19091, 19605,…
$ NH_W_F    <dbl> NA, 19101, 18114, 18043, 17786, 18366, 18386, 18047, 18316,…
$ NH_B_M    <dbl> NA, 9794, 9475, 9097, 9002, 9076, 9169, 8919, 9219, 9247, 1…
$ NH_B_F    <dbl> NA, 9414, 9247, 8837, 8701, 8989, 9093, 8736, 9192, 9108, 9…
$ NH_AIAN_M <dbl> NA, 103, 87, 97, 94, 108, 128, 160, 178, 166, 205, 194, 179…
$ NH_AIAN_F <dbl> NA, 90, 93, 100, 115, 114, 130, 134, 162, 155, 193, 185, 20…
$ NH_API_M  <dbl> NA, 192, 146, 175, 150, 168, 170, 183, 171, 136, 177, 169, …
$ NH_API_F  <dbl> NA, 170, 182, 160, 157, 178, 158, 173, 177, 185, 179, 171, …
$ H_W_M     <dbl> NA, 223, 190, 198, 186, 190, 210, 188, 178, 182, 221, 194, …
$ H_W_F     <dbl> NA, 220, 196, 173, 191, 190, 170, 172, 179, 173, 166, 175, …
$ H_B_M     <dbl> NA, 47, 41, 32, 35, 36, 30, 28, 27, 29, 32, 31, 33, 34, 32,…
$ H_B_F     <dbl> NA, 45, 47, 41, 30, 26, 37, 23, 35, 31, 28, 38, 22, 39, 29,…
$ H_AIAN_M  <dbl> NA, 1, 2, 1, 9, 5, 8, 2, 4, 6, 6, 0, 1, 9, 6, 7, 5, 2, 2, 4…
$ H_AIAN_F  <dbl> NA, 8, 0, 2, 1, 4, 5, 3, 4, 4, 3, 4, 2, 2, 7, 0, 2, 2, 1, 6…
$ H_API_M   <dbl> NA, 5, 7, 2, 3, 5, 11, 2, 7, 12, 10, 7, 5, 6, 5, 6, 6, 2, 1…
$ H_API_F   <dbl> NA, 5, 5, 5, 3, 14, 6, 7, 6, 3, 11, 5, 5, 7, 8, 6, 6, 7, 3,…

Notice also that the first row is all NA values from white space in the orginal table for 1990, this is probably true for each year. We can check them dimensions of our table using the base dim() function. When we filter for rows where YEAR is NA, we indeed see 10 rows, which is what we would expect if we have a row like this for each of the years in the decade. We see the same if we try a different variable. Now we will test to see how large our tibble is if we drop rows with NA values using the drop_na() function of tidyr. We that indeed our dimensions only changed by ten, so there are not other rows with missing values that we might not expect. So now we will resign the dem_90_99 variable after removing these rows.

[1] 43870    19
# A tibble: 10 x 19
    YEAR STATEFP   Age NH_W_M NH_W_F NH_B_M NH_B_F NH_AIAN_M NH_AIAN_F NH_API_M
   <dbl> <chr>   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
 1    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 2    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 3    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 4    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 5    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 6    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 7    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 8    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 9    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
10    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
# … with 9 more variables: NH_API_F <dbl>, H_W_M <dbl>, H_W_F <dbl>,
#   H_B_M <dbl>, H_B_F <dbl>, H_AIAN_M <dbl>, H_AIAN_F <dbl>, H_API_M <dbl>,
#   H_API_F <dbl>
# A tibble: 10 x 19
    YEAR STATEFP   Age NH_W_M NH_W_F NH_B_M NH_B_F NH_AIAN_M NH_AIAN_F NH_API_M
   <dbl> <chr>   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
 1    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 2    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 3    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 4    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 5    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 6    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 7    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 8    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
 9    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
10    NA <NA>       NA     NA     NA     NA     NA        NA        NA       NA
# … with 9 more variables: NH_API_F <dbl>, H_W_M <dbl>, H_W_F <dbl>,
#   H_B_M <dbl>, H_B_F <dbl>, H_AIAN_M <dbl>, H_AIAN_F <dbl>, H_API_M <dbl>,
#   H_API_F <dbl>
# A tibble: 43,860 x 19
    YEAR STATEFP   Age NH_W_M NH_W_F NH_B_M NH_B_F NH_AIAN_M NH_AIAN_F NH_API_M
   <dbl> <chr>   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
 1  1990 01          0  20406  19101   9794   9414       103        90      192
 2  1990 01          1  19393  18114   9475   9247        87        93      146
 3  1990 01          2  18990  18043   9097   8837        97       100      175
 4  1990 01          3  19246  17786   9002   8701        94       115      150
 5  1990 01          4  19502  18366   9076   8989       108       114      168
 6  1990 01          5  19560  18386   9169   9093       128       130      170
 7  1990 01          6  19091  18047   8919   8736       160       134      183
 8  1990 01          7  19605  18316   9219   9192       178       162      171
 9  1990 01          8  18823  17743   9247   9108       166       155      136
10  1990 01          9  20226  19178  10194   9784       205       193      177
# … with 43,850 more rows, and 9 more variables: NH_API_F <dbl>, H_W_M <dbl>,
#   H_W_F <dbl>, H_B_M <dbl>, H_B_F <dbl>, H_AIAN_M <dbl>, H_AIAN_F <dbl>,
#   H_API_M <dbl>, H_API_F <dbl>

Then we sum across the nonhispanic and hispaninc groups because this information is not available for the other previous decades. Then we will remove the variables for the hispanic and nonhispanic subgroups using select().

Rows: 43,860
Columns: 11
$ YEAR    <dbl> 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1…
$ STATEFP <chr> "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", "…
$ Age     <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,…
$ W_M     <dbl> 20629, 19583, 19188, 19432, 19692, 19770, 19279, 19783, 19005…
$ W_F     <dbl> 19321, 18310, 18216, 17977, 18556, 18556, 18219, 18495, 17916…
$ B_M     <dbl> 9841, 9516, 9129, 9037, 9112, 9199, 8947, 9246, 9276, 10226, …
$ B_F     <dbl> 9459, 9294, 8878, 8731, 9015, 9130, 8759, 9227, 9139, 9812, 1…
$ AIAN_M  <dbl> 104, 89, 98, 103, 113, 136, 162, 182, 172, 211, 194, 180, 209…
$ AIAN_F  <dbl> 98, 93, 102, 116, 118, 135, 137, 166, 159, 196, 189, 204, 198…
$ API_M   <dbl> 197, 153, 177, 153, 173, 181, 185, 178, 148, 187, 176, 164, 1…
$ API_F   <dbl> 175, 187, 165, 160, 192, 164, 180, 183, 188, 190, 176, 168, 1…

Looking better! We also need to add age groups like the other decades. We will take a look at the 80s data using the distinct() function of the dplyr package to see what age groups we need. We can use the base cut() function to create a new variable with mutate() called AGE_GROUP that will have a label for every change in 5 years of age. The right = FALSE argument specifies that the interval is not closed on the right, meaning that if the value is at the cutpoint like the Age value is 5, then it will be in the 5 to 9 years group.

We can make the labels for the AGE_GROUP variable match those of dem_77_79 but we need to pull out the values of the tibble created by distinct(). To do this we can use the pull() function from the dplyr package. Note that it is important to check that the AGE_GROUP values are listed in order for dem_77_79. We will also remove the Age variable after we create the new AGE_GROUP variable for the dem_90_99 data.

# A tibble: 18 x 1
   AGE_GROUP        
   <chr>            
 1 Under 5 years    
 2 5 to 9 years     
 3 10 to 14 years   
 4 15 to 19 years   
 5 20 to 24 years   
 6 25 to 29 years   
 7 30 to 34 years   
 8 35 to 39 years   
 9 40 to 44 years   
10 45 to 49 years   
11 50 to 54 years   
12 55 to 59 years   
13 60 to 64 years   
14 65 to 69 years   
15 70 to 74 years   
16 75 to 79 years   
17 80 to 84 years   
18 85 years and over
 [1] "Under 5 years"     "5 to 9 years"      "10 to 14 years"   
 [4] "15 to 19 years"    "20 to 24 years"    "25 to 29 years"   
 [7] "30 to 34 years"    "35 to 39 years"    "40 to 44 years"   
[10] "45 to 49 years"    "50 to 54 years"    "55 to 59 years"   
[13] "60 to 64 years"    "65 to 69 years"    "70 to 74 years"   
[16] "75 to 79 years"    "80 to 84 years"    "85 years and over"
Rows: 43,860
Columns: 11
$ YEAR      <dbl> 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990,…
$ STATEFP   <chr> "01", "01", "01", "01", "01", "01", "01", "01", "01", "01",…
$ W_M       <dbl> 20629, 19583, 19188, 19432, 19692, 19770, 19279, 19783, 190…
$ W_F       <dbl> 19321, 18310, 18216, 17977, 18556, 18556, 18219, 18495, 179…
$ B_M       <dbl> 9841, 9516, 9129, 9037, 9112, 9199, 8947, 9246, 9276, 10226…
$ B_F       <dbl> 9459, 9294, 8878, 8731, 9015, 9130, 8759, 9227, 9139, 9812,…
$ AIAN_M    <dbl> 104, 89, 98, 103, 113, 136, 162, 182, 172, 211, 194, 180, 2…
$ AIAN_F    <dbl> 98, 93, 102, 116, 118, 135, 137, 166, 159, 196, 189, 204, 1…
$ API_M     <dbl> 197, 153, 177, 153, 173, 181, 185, 178, 148, 187, 176, 164,…
$ API_F     <dbl> 175, 187, 165, 160, 192, 164, 180, 183, 188, 190, 176, 168,…
$ AGE_GROUP <fct> Under 5 years, Under 5 years, Under 5 years, Under 5 years,…

Like the previous decades we will create a RACE and SUB_POP variable using pivot_longer() to create a single Race variable out of all the subgroup variables.

Now we need to collapse the data for the various races so that it matches the previous decades. This time we will use the case_when() function of the dplyr package and the str_detect() function of the stringr package to identify when the race is something other than B or W and replace with the value Other. The value to the right of the ~ indicates what we want the value of the new variable to be if the value of the variable we are using with str_decect() matches the condition specified. If the value does not match the specified condition, than the other values will be what ever is listed after TRUE ~. We will then create population counts as we did previously for the other decades.

Finally, we will create new sums for the subpopulations where we sum across the two Other subgroups Race to a create a single value for each value of YEAR, SEX, AGE_GROUP, and STATE by using the group_by() function and summarie().

# A tibble: 55,080 x 6
    YEAR STATE   AGE_GROUP     SEX    RACE  PERC_SUB_POP
   <dbl> <chr>   <fct>         <chr>  <chr>        <dbl>
 1  1990 Alabama Under 5 years Female Black       1.12  
 2  1990 Alabama Under 5 years Female Other       0.0347
 3  1990 Alabama Under 5 years Female White       2.28  
 4  1990 Alabama Under 5 years Male   Black       1.15  
 5  1990 Alabama Under 5 years Male   Other       0.0336
 6  1990 Alabama Under 5 years Male   White       2.43  
 7  1990 Alabama 5 to 9 years  Female Black       1.14  
 8  1990 Alabama 5 to 9 years  Female Other       0.0419
 9  1990 Alabama 5 to 9 years  Female White       2.29  
10  1990 Alabama 5 to 9 years  Male   Black       1.16  
# … with 55,070 more rows

Again, we should check to make sure that we have the total values we would expect. We have the same number of unique values for each of our variables as in with the data from the 80s, so if we collpased the data for the different additional subpopulations in this data, then we have done it correctly.

Indeed it looks like we have 55,080 rows, which is what we would expect and is the same as the number of rows of the final dem_80_89 data. Looks good!

2000-2010


Again, for this decade we need to combine the data across years.

Rows: 62,244
Columns: 21
$ REGION            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ DIVISION          <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ STATE             <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ NAME              <chr> "United States", "United States", "United States", …
$ SEX               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ ORIGIN            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ RACE              <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ AGEGRP            <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1…
$ ESTIMATESBASE2000 <dbl> 281424600, 19176154, 20549855, 20528425, 20218782, …
$ POPESTIMATE2000   <dbl> 282162411, 19178293, 20463852, 20637696, 20294955, …
$ POPESTIMATE2001   <dbl> 284968955, 19298217, 20173362, 20978678, 20456284, …
$ POPESTIMATE2002   <dbl> 287625193, 19429192, 19872417, 21261421, 20610370, …
$ POPESTIMATE2003   <dbl> 290107933, 19592446, 19620851, 21415353, 20797166, …
$ POPESTIMATE2004   <dbl> 292805298, 19785885, 19454237, 21411680, 21102552, …
$ POPESTIMATE2005   <dbl> 295516599, 19917400, 19389067, 21212579, 21486214, …
$ POPESTIMATE2006   <dbl> 298379912, 19938883, 19544688, 21033138, 21807709, …
$ POPESTIMATE2007   <dbl> 301231207, 20125962, 19714611, 20841042, 22067816, …
$ POPESTIMATE2008   <dbl> 304093966, 20271127, 19929602, 20706655, 22210880, …
$ POPESTIMATE2009   <dbl> 306771529, 20244518, 20182499, 20660564, 22192810, …
$ CENSUS2010POP     <dbl> 308745538, 20201362, 20348657, 20677194, 22040343, …
$ POPESTIMATE2010   <dbl> 309349689, 20200529, 20382409, 20694011, 21959087, …

Ok, the data looks a bit different from the others. First we will remove a couple of variables that we probably don’t need. Also it looks like we have some values for the entire United Sates and we will drop these to be like the other decades.

We can see that there are lots of values that are zero. According to the technical documentation for this data, zero values indicate the total for the other categories of Sex, Origin, Race, and AGEGRP.

So we will drop the total values for SEX, RACE, and AGEGRP by removing the rows where these variables are equal to zero.

We will also want to only select for the total values for Origin as we do not wish to divide the data into subgroups about hispanic ethnicity because we do not have that information for the first two decades. Thus we will filter for only the rows where Origin is equal to zero.

We will also then remove the REGION, Division, STATE, and Origin variables. We will then rename NAME to be STATE and rename AGEGRP to be like the other decades as AGE_GROUP.

# A tibble: 11,016 x 15
   STATE   SEX  RACE AGE_GROUP POPESTIMATE2000 POPESTIMATE2001 POPESTIMATE2002
   <chr> <dbl> <dbl>     <dbl>           <dbl>           <dbl>           <dbl>
 1 Alab…     1     1         1           99527           99985           99578
 2 Alab…     1     1         2          104423          102518          101023
 3 Alab…     1     1         3          108325          108412          108059
 4 Alab…     1     1         4          108638          107370          107337
 5 Alab…     1     1         5          104337          107230          108195
 6 Alab…     1     1         6          106491          101466           98949
 7 Alab…     1     1         7          110116          110630          110416
 8 Alab…     1     1         8          123719          120283          116502
 9 Alab…     1     1         9          124961          125443          124751
10 Alab…     1     1        10          115024          117010          119354
# … with 11,006 more rows, and 8 more variables: POPESTIMATE2003 <dbl>,
#   POPESTIMATE2004 <dbl>, POPESTIMATE2005 <dbl>, POPESTIMATE2006 <dbl>,
#   POPESTIMATE2007 <dbl>, POPESTIMATE2008 <dbl>, POPESTIMATE2009 <dbl>,
#   POPESTIMATE2010 <dbl>

Now we need to recode the numeric values to the values in the techincal documentation. We can do so by adding labels to each numeric level using the base function factor().

Rows: 11,016
Columns: 15
$ STATE           <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Alabama"…
$ SEX             <fct> Male, Male, Male, Male, Male, Male, Male, Male, Male,…
$ RACE            <fct> White, White, White, White, White, White, White, Whit…
$ AGE_GROUP       <fct> Under 5 years, 5 to 9 years, 10 to 14 years, 15 to 19…
$ POPESTIMATE2000 <dbl> 99527, 104423, 108325, 108638, 104337, 106491, 110116…
$ POPESTIMATE2001 <dbl> 99985, 102518, 108412, 107370, 107230, 101466, 110630…
$ POPESTIMATE2002 <dbl> 99578, 101023, 108059, 107337, 108195, 98949, 110416,…
$ POPESTIMATE2003 <dbl> 99627, 99920, 108026, 107749, 109360, 98276, 109893, …
$ POPESTIMATE2004 <dbl> 99788, 99306, 107627, 108666, 109037, 98742, 107653, …
$ POPESTIMATE2005 <dbl> 100316, 99754, 106570, 110278, 108727, 100327, 105151…
$ POPESTIMATE2006 <dbl> 100820, 101251, 106228, 111640, 108847, 103869, 10161…
$ POPESTIMATE2007 <dbl> 101766, 101985, 106243, 112353, 109496, 105175, 99917…
$ POPESTIMATE2008 <dbl> 102304, 102479, 106155, 113305, 110007, 106348, 99921…
$ POPESTIMATE2009 <dbl> 101411, 102688, 106130, 113741, 111167, 106497, 10138…
$ POPESTIMATE2010 <dbl> 99480, 102939, 106324, 112272, 112423, 106593, 102923…

OK, we also want to change the shape of the data so that we have a YEAR variable and each estimate of the population is a value in a new variable called SUB_POP_temp.

We will now clean up the YEAR variable to only be the numeric value by keeping only the last 4 values of each string using the str_sub() function of the stringr package.

Now we will collapse the data for the different RACES and calculate a new SUB_POP value.

Agian, the dimensions look as we expect with 60,588 rows. This time we have two levels of SEX, three levels of Race, 11 levels of YEAR, eighteen levels of AGE_GROUP, and fifty one levels of STATE. If we multiply this together we get 16,588. Looks good!

Now we will calculate the total polutation and percent of the total as we have done with the previous decades.

We can also check that our wrangling was performecd correctly by summing the values for the individual subpopulations percentages and seeing if it totals to 100.

# A tibble: 1 x 2
  poss_error     n
  <lgl>      <int>
1 FALSE        561

Looks like the percentages for each state for each year all add up to 100, as we would expect. Great! Now we will reasign the dem_00_10 data with this processing.

# A tibble: 60,588 x 6
    YEAR AGE_GROUP     STATE   SEX    RACE  PERC_SUB_POP
   <dbl> <fct>         <chr>   <fct>  <fct>        <dbl>
 1  2000 Under 5 years Alabama Male   White       2.24  
 2  2000 Under 5 years Alabama Male   Black       1.05  
 3  2000 Under 5 years Alabama Male   Other       0.101 
 4  2000 Under 5 years Alabama Female White       2.12  
 5  2000 Under 5 years Alabama Female Black       1.03  
 6  2000 Under 5 years Alabama Female Other       0.0995
 7  2000 Under 5 years Alaska  Male   White       2.35  
 8  2000 Under 5 years Alaska  Male   Black       0.165 
 9  2000 Under 5 years Alaska  Male   Other       1.37  
10  2000 Under 5 years Alaska  Female White       2.26  
# … with 60,578 more rows

OK, now we are ready to combine all of our demgraphic data together!

Combining demographic data

We can check that the colnames are the same for the data for each of the decades by using the setequal() function of the dplyr package.

[1] TRUE
[1] TRUE
[1] TRUE

We can also confirm that we have the same number of age groups for each decade by using the base length() function. If you did not take a look at the wrangling for the demographic data then you may be unfamiliar with the pull() function of the dplyr package. This allows you to grab the values of a variable from a tibble. The distinct() function which is also of the dplyr package creates a tibble of the unique values for a variable.

[1] 18
[1] 18
[1] 18
[1] 18

Looks good!

Now we will combine the data using the bind_rows() function of the dplyr package. This function appends the data together based on the presence of columns with the same name in the different tibbles.

Rows: 187,272
Columns: 6
$ YEAR         <dbl> 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977, 19…
$ STATE        <chr> "Alabama", "Alabama", "Alabama", "Alabama", "Alabama", "…
$ SEX          <chr> "Male", "Male", "Male", "Male", "Male", "Male", "Male", …
$ RACE         <chr> "White", "White", "White", "White", "White", "White", "W…
$ AGE_GROUP    <chr> "Under 5 years", "5 to 9 years", "10 to 14 years", "15 t…
$ PERC_SUB_POP <dbl> 2.6123502, 2.9970356, 3.2545853, 3.5780690, 3.3324688, 2…

Great! now we have a really large single tibble.

Now we want to select similar demographic data to what was used in the previous analyses.

Here is the table from the Donohue paper that compares the data used in the analyses.

We can see that only the percentage of males that were from age 15-39 of the race groups (black, white, and other) were used in the Donohue analysis.

Ultimately we intend to make a tibble of data that is similar to each analysis. Therefore, we will create a data tibble about the demogrphaic data for each analysis now.

To do so we will first create a vector of the age groups that should be included in the Donohue-like analysis, that we will call DONOHUE_AGE_GROUPS. We will then filter for only the age groups in this vector by using the filter() function of the dplyr package and the %in% operator to indicate that we want to keep all AGE_GROUP values that are equal to those within DONOHUE_AGE_GROUPS. We also want to filter for only population percentages for males by using the == operator. Then we can collpase the age groups from 20-39 by using the fct_collpase() function of the forcats package.

# A tibble: 26,010 x 6
    YEAR STATE   SEX   RACE  AGE_GROUP      PERC_SUB_POP
   <dbl> <chr>   <chr> <chr> <fct>                 <dbl>
 1  1977 Alabama Male  White 15 to 19 years        3.58 
 2  1977 Alabama Male  White 20 to 39 years        3.33 
 3  1977 Alabama Male  White 20 to 39 years        2.95 
 4  1977 Alabama Male  White 20 to 39 years        2.66 
 5  1977 Alabama Male  White 20 to 39 years        2.14 
 6  1977 Alabama Male  Black 15 to 19 years        1.55 
 7  1977 Alabama Male  Black 20 to 39 years        1.16 
 8  1977 Alabama Male  Black 20 to 39 years        0.820
 9  1977 Alabama Male  Black 20 to 39 years        0.596
10  1977 Alabama Male  Black 20 to 39 years        0.462
# … with 26,000 more rows

We also want to create a new variable that will contain all the demographic information for each percentage just as was done in the Donohue, et al. analysis. This should result in 6 different demographic variables.

To do this we will modify the AGE_GROUP variable by using the mutate() function of the dplyr package. We will replace the spaces in the now two age group categorise with and undesrscore using the str_replace_all() function of the stringr package which replaces all instances of a pattern in a character string.

Then we will use the group_by() function and the summarise() funtion also of the dplyr package to allow us to calculate a sum of the percentages for each of the subpopulation percentages for the newly modifed age groups in AGE_GROUP. The .groups = "drop" argument allows for the grouping to be removed after the summarise() function.

# A tibble: 10,404 x 6
    YEAR STATE   RACE  SEX   AGE_GROUP      PERC_SUB_POP
   <dbl> <chr>   <chr> <chr> <chr>                 <dbl>
 1  1977 Alabama Black Male  15_to_19_years       1.55  
 2  1977 Alabama Black Male  20_to_39_years       3.04  
 3  1977 Alabama Other Male  15_to_19_years       0.0178
 4  1977 Alabama Other Male  20_to_39_years       0.0642
 5  1977 Alabama White Male  15_to_19_years       3.58  
 6  1977 Alabama White Male  20_to_39_years      11.1   
 7  1977 Alaska  Black Male  15_to_19_years       0.163 
 8  1977 Alaska  Black Male  20_to_39_years       0.968 
 9  1977 Alaska  Other Male  15_to_19_years       1.12  
10  1977 Alaska  Other Male  20_to_39_years       2.73  
# … with 10,394 more rows

Now we will combine the variables RACE, SEX, and AGE_GROUP together into one string separated by underscores using the unite function of the tidyr package. we will call this new variable VARIABLE. We will rename the PERC_SUB_POP variable to be VALUE using the rename() function of the dplyr package. The new name should be listed first before the =.

# A tibble: 10,404 x 4
    YEAR STATE   VARIABLE                    VALUE
   <dbl> <chr>   <chr>                       <dbl>
 1  1977 Alabama Black_Male_15_to_19_years  1.55  
 2  1977 Alabama Black_Male_20_to_39_years  3.04  
 3  1977 Alabama Other_Male_15_to_19_years  0.0178
 4  1977 Alabama Other_Male_20_to_39_years  0.0642
 5  1977 Alabama White_Male_15_to_19_years  3.58  
 6  1977 Alabama White_Male_20_to_39_years 11.1   
 7  1977 Alaska  Black_Male_15_to_19_years  0.163 
 8  1977 Alaska  Black_Male_20_to_39_years  0.968 
 9  1977 Alaska  Other_Male_15_to_19_years  1.12  
10  1977 Alaska  Other_Male_20_to_39_years  2.73  
# … with 10,394 more rows

Let’s do a quick row number check. We have six different demographic variables, 51 states (DC counts as a state in this case), and 34 different years from 1977 to 2010, we should have 10,404 rows, which we do!

Now, let’s do the same for the “Lott-like” analysis.

So, in this analysis there were 36 variables covering percentages of indiviuals from 10 to over 65, three race groups and both males and females. This table is misprinted and does not include the word “Other” for the third race group that was used.

First we will filter out the age groups that were not included. Then we will collapse the age groups to those that were used by Lott et al. again using the fct_collpase() function of the forcats package.

Also we will again combine the values across the variables to create a new demographic varaible with 36 levels.

We can indeed check that we have the correct number of levels for VARIABLE using the distinct() function.

# A tibble: 36 x 1
   VARIABLE                      
   <chr>                         
 1 Black_Female_10_to_19_years   
 2 Black_Female_20_to_29_years   
 3 Black_Female_30_to_39_years   
 4 Black_Female_40_to_49_years   
 5 Black_Female_50_to_64_years   
 6 Black_Female_65_years_and_over
 7 Black_Male_10_to_19_years     
 8 Black_Male_20_to_29_years     
 9 Black_Male_30_to_39_years     
10 Black_Male_40_to_49_years     
# … with 26 more rows

Combining population Data

We also have population data for each decade that came from wrangling of the demogrphic data.

We again want to combine this data, so let’s again make sure that all the different tibbles have the same column names.

[1] TRUE
[1] TRUE
[1] TRUE
# A tibble: 6 x 3
   YEAR STATE       TOT_POP
  <dbl> <chr>         <dbl>
1  1977 Alabama     3782571
2  1977 Alaska       397220
3  1977 Arizona     2427296
4  1977 Arkansas    2207195
5  1977 California 22350332
6  1977 Colorado    2696179
# A tibble: 6 x 3
   YEAR STATE       TOT_POP
  <dbl> <chr>         <dbl>
1  1980 Alabama     3899671
2  1980 Alaska       404680
3  1980 Arizona     2735840
4  1980 Arkansas    2288809
5  1980 California 23792840
6  1980 Colorado    2909545
# A tibble: 6 x 3
   YEAR STATE       TOT_POP
  <dbl> <chr>         <dbl>
1  1990 Alabama     4048508
2  1990 Alaska       553120
3  1990 Arizona     3679056
4  1990 Arkansas    2354343
5  1990 California 29950111
6  1990 Colorado    3303862
# A tibble: 6 x 3
   YEAR STATE       TOT_POP
  <dbl> <chr>         <dbl>
1  2000 Alabama     4452173
2  2000 Alaska       627963
3  2000 Arizona     5160586
4  2000 Arkansas    2678588
5  2000 California 33987977
6  2000 Colorado    4326921

Looks good!

We could check that we have 51 values for each year by using the count() function of the dplyr package.

# A tibble: 34 x 2
    YEAR     n
   <dbl> <int>
 1  1977    51
 2  1978    51
 3  1979    51
 4  1980    51
 5  1981    51
 6  1982    51
 7  1983    51
 8  1984    51
 9  1985    51
10  1986    51
# … with 24 more rows

Police staffing

click here to see detials about how the plice staffing data was wrangled.

OK, now we will wrangle the police staffing data. We want to limit the data to only the years of interest. Then we will also replace NA values with zero for the male_total_ct and female_total_ct variables using the replace_na() function of the tidyr packge. We will also, use the across() function of the dplyr package to select and mutate both of these columns in this way. Since both of these variables have total_ct in the name and no other variables do, we can use the contains() function of the dplyr package to specify that we want to use these columns instead of listing both out.

avocado… why not 2010….

Rows: 1,439,467
Columns: 21
$ data_year             <dbl> 1960, 1960, 1960, 1960, 1960, 1960, 1960, 1960,…
$ ori                   <chr> "AK020045Y", "AL0011000", "AL0160600", "AL01900…
$ pub_agency_name       <chr> "Alcohol Beverage Control Board", "Homewood", "…
$ pub_agency_unit       <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ state_abbr            <chr> "AK", "AL", "AL", "AL", "AL", "AL", "AL", "AL",…
$ division_name         <chr> "Pacific", "East South Central", "East South Ce…
$ region_name           <chr> "West", "South", "South", "South", "South", "So…
$ county_name           <chr> "N/A", "JEFFERSON", "N/A", "COFFEE", "N/A", "HA…
$ agency_type_name      <chr> "Other State Agency", "City", "City", "County",…
$ population_group_desc <chr> "Cities under 2,500", "Cities from 10,000 thru …
$ population            <dbl> 0, 20289, 0, 14852, 0, 3081, 0, 18739, 2776, 0,…
$ male_officer_ct       <dbl> NA, 17, NA, 0, NA, 0, NA, 0, 0, NA, NA, 0, NA, …
$ male_civilian_ct      <dbl> NA, 3, NA, 0, NA, 0, NA, 0, 0, NA, NA, 0, NA, N…
$ male_total_ct         <dbl> NA, 20, NA, 0, NA, 0, NA, 0, 0, NA, NA, 0, NA, …
$ female_officer_ct     <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ female_civilian_ct    <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ female_total_ct       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ officer_ct            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ civilian_ct           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ total_pe_ct           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ pe_ct_per_1000        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
Rows: 932,063
Columns: 21
$ data_year             <dbl> 1977, 1977, 1977, 1977, 1977, 1977, 1977, 1977,…
$ ori                   <chr> "AK0012000", "AK0012300", "AKASP0000", "AL00125…
$ pub_agency_name       <chr> "Soldotna", "Kenai", "Alaska State Troopers", "…
$ pub_agency_unit       <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ state_abbr            <chr> "AK", "AK", "AK", "AL", "AL", "AL", "AL", "AL",…
$ division_name         <chr> "Pacific", "Pacific", "Pacific", "East South Ce…
$ region_name           <chr> "West", "West", "West", "South", "South", "Sout…
$ county_name           <chr> "KENAI PENINSULA", "KENAI PENINSULA", "N/A", "J…
$ agency_type_name      <chr> "City", "City", "State Police", "City", "Other"…
$ population_group_desc <chr> "Cities under 2,500", "Cities from 2,500 thru 9…
$ population            <dbl> 2131, 5800, 172397, 1000, 0, 8611, 2850, 975, 2…
$ male_officer_ct       <dbl> 6, 10, 0, 3, NA, 16, 6, 2, 5, NA, NA, 3, 26, 5,…
$ male_civilian_ct      <dbl> 6, 0, 0, 0, NA, 5, 0, 0, 0, NA, NA, 0, 0, 0, 4,…
$ male_total_ct         <dbl> 12, 10, 0, 3, 0, 21, 6, 2, 5, 0, 0, 3, 26, 5, 6…
$ female_officer_ct     <lgl> FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, FALS…
$ female_civilian_ct    <lgl> TRUE, NA, NA, FALSE, NA, FALSE, FALSE, FALSE, F…
$ female_total_ct       <dbl> 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 13, 0…
$ officer_ct            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ civilian_ct           <lgl> NA, NA, NA, FALSE, NA, NA, FALSE, FALSE, FALSE,…
$ total_pe_ct           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ pe_ct_per_1000        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…

Now we can create a new variable called officer_total that is the sum of these variables. We will then keep just this variable as well as the data_year, pub_agency_name, and state_abbr.

# A tibble: 932,063 x 4
   data_year pub_agency_name                            state_abbr officer_total
       <dbl> <chr>                                      <chr>              <dbl>
 1      1977 Soldotna                                   AK                    13
 2      1977 Kenai                                      AK                    15
 3      1977 Alaska State Troopers                      AK                     0
 4      1977 Trafford                                   AL                     3
 5      1977 Trussville Fire Department Fire and Explo… AL                     0
 6      1977 Atmore                                     AL                    21
 7      1977 East Brewton                               AL                     6
 8      1977 Brilliant                                  AL                     2
 9      1977 Camden                                     AL                     5
10      1977 Drug Enforcement Administration, Birmingh… AL                     0
# … with 932,053 more rows

Now we also want to get collapse by pub_agency_name to get a total count for each year and each state. So we will do this by using the group_by() function and grouping by data_year and state_abbr and using the summarise() function to calculate a sum.

# A tibble: 2,242 x 3
   data_year state_abbr officer_state_total
       <dbl> <chr>                    <dbl>
 1      1977 AK                         544
 2      1977 AL                        7380
 3      1977 AR                        3344
 4      1977 AS                           0
 5      1977 AZ                        6414
 6      1977 CA                       65596
 7      1977 CO                        7337
 8      1977 CT                        6051
 9      1977 CZ                           0
10      1977 DC                        4751
# … with 2,232 more rows

And we will check that we have same number of values (the number of years included in the data) for each state.

# A tibble: 59 x 2
   state_abbr     n
   <chr>      <int>
 1 AK            38
 2 AL            38
 3 AR            38
 4 AS            38
 5 AZ            38
 6 CA            38
 7 CO            38
 8 CT            38
 9 CZ            38
10 DC            38
# … with 49 more rows

We will remove a few states now. AVocado- why? NB is Nebraska. This was changed to NE to avoid confusions with NB in Canada. This dataset uses NB

   state_abbr          STATE
1          AL        Alabama
2          AK         Alaska
3          AZ        Arizona
4          AR       Arkansas
5          CA     California
6          CO       Colorado
7          CT    Connecticut
8          DE       Delaware
9          FL        Florida
10         GA        Georgia
11         HI         Hawaii
12         ID          Idaho
13         IL       Illinois
14         IN        Indiana
15         IA           Iowa
16         KS         Kansas
17         KY       Kentucky
18         LA      Louisiana
19         ME          Maine
20         MD       Maryland
21         MA  Massachusetts
22         MI       Michigan
23         MN      Minnesota
24         MS    Mississippi
25         MO       Missouri
26         MT        Montana
27         NE       Nebraska
28         NV         Nevada
29         NH  New Hampshire
30         NJ     New Jersey
31         NM     New Mexico
32         NY       New York
33         NC North Carolina
34         ND   North Dakota
35         OH           Ohio
36         OK       Oklahoma
37         OR         Oregon
38         PA   Pennsylvania
39         RI   Rhode Island
40         SC South Carolina
41         SD   South Dakota
42         TN      Tennessee
43         TX          Texas
44         UT           Utah
45         VT        Vermont
46         VA       Virginia
47         WA     Washington
48         WV  West Virginia
49         WI      Wisconsin
50         WY        Wyoming

Unemployment

The first thing we need to do with the unemployment data is combine the data across the different states. We can do that using the bind_rows() function of dplyr which appends the data together based on the presence of columns with the same name in the different tibbles. We will use the map_df() function of the purrr package to allow us to do this across each tibble in our list. We will then select just the annual data for each state and we will rename our variables to be consistent with some of other data.

# A tibble: 6 x 15
  STATE   Year   Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov
  <chr>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Alaba…  1977   7.5   9     7.7   7.2   6.8   8.6   8     7.8   6.7   6.3   6.3
2 Alaba…  1978   7.1   6.9   6.2   5.4   5.1   6.9   6.7   6.7   6.5   6.3   6.3
3 Alaba…  1979   6.7   7.5   6.9   6.6   6.4   8.4   7.7   7.8   7.1   7.2   6.9
4 Alaba…  1980   7.7   7.8   7.4   7.4   8.4   9.7  10.4  10.3   9.3   9.6   9.4
5 Alaba…  1981  10    10.3   9.5   9.1   9.4  11.1  10.4  10.9  10.8  11.7  11.5
6 Alaba…  1982  13.2  13.2  12.9  12.6  12.8  14.5  14.7  14.8  14.7  15.1  15.4
# … with 2 more variables: Dec <dbl>, Annual <dbl>

Poverty rate

# A tibble: 6 x 6
  `NOTE: Number in thousa… ...2  ...3   ...4         ...5         ...6          
  <chr>                    <chr> <chr>  <chr>        <chr>        <chr>         
1 2018                     <NA>  <NA>    <NA>        <NA>          <NA>         
2 STATE                    Total Number "Standard\n… Percent      "Standard\ner…
3 Alabama                  4877  779    "65"         16           "1.3"         
4 Alaska                   720   94     "9"          13.1         "1.2"         
5 Arizona                  7241  929    "80"         12.80000000… "1.1000000000…
6 Arkansas                 2912  462    "38"         15.9         "1.3"         
# A tibble: 6 x 6
  STATE                             Total Number Number_se Percent Percent_se   
  <chr>                             <chr> <chr>  <chr>     <chr>   <chr>        
1 Wisconsin                         4724  403    57        8.5     1.1000000000…
2 Wyoming                           468   49     20        10.4    4            
3 Standard errors shown in this ta… <NA>  <NA>   <NA>      <NA>    <NA>         
4 For information on confidentiali… <NA>  <NA>   <NA>      <NA>    <NA>         
5 Footnotes are available at <www.… <NA>  <NA>   <NA>      <NA>    <NA>         
6 SOURCE: U.S. Bureau of the Censu… <NA>  <NA>   <NA>      <NA>    <NA>         
[1] "2 extra groups"
# A tibble: 6 x 7
  STATE   Total Number Number_se      Percent        Percent_se       year_group
  <chr>   <chr> <chr>  <chr>          <chr>          <chr>                 <int>
1 2018    <NA>  <NA>    <NA>          <NA>            <NA>                     1
2 STATE   Total Number "Standard\ner… Percent        "Standard\nerro…          1
3 Alabama 4877  779    "65"           16             "1.3"                     1
4 Alaska  720   94     "9"            13.1           "1.2"                     1
5 Arizona 7241  929    "80"           12.8000000000… "1.100000000000…          1
6 Arkans… 2912  462    "38"           15.9           "1.3"                     1
# A tibble: 2 x 2
   n_na     n
  <dbl> <int>
1     0  1989
2     5    39
       YEAR       STATE       Total      Number   Number_se     Percent 
"character" "character" "character" "character" "character" "character" 
 Percent_se        n_na 
"character"   "numeric" 
[1] "YEAR"     "STATE"    "VALUE"    "VARIABLE"

Violent crime

https://www.ucrdatatool.gov/Search/Crime/State/StatebyState.cfm

[1] 2254
       YEAR          VC       STATE 
"character" "character" "character" 

RTC laws

 [1] 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109
[20] 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109
[39] 109 109 109 109 109 109 109 109 109 109 109 109 109 109  63
[1] "                                                             60"
 [1] 3 4 4 4 3 4 2 3 2 4 4 3 4 3 4 4 4 4 4 4 3 2 4 4 4 4 4 4 4 2 3 3 3 3 3 4 4 4
[39] 3 3 2 3 3 4 4 4 3 4 2 3 4 4
 [1] 2 3 3 3 2 3 2 2 2 3 3 2 3 2 3 3 3 3 3 3 2 2 3 3 3 3 3 3 3 2 2 3 2 3 3 3 3 3
[39] 3 3 2 3 3 3 3 3 2 3 2 3 3 3
 [1] 2 2 2 2 1 2 1 1 1 2 2 2 2 1 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2
[39] 2 2 1 2 2 2 2 2 2 2 1 2 2 2
 [1] 1 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0
[39] 0 0 1 0 0 0 0 0 1 0 1 0 0 0
                                                                                                              .
1       Alabama                    1975                                                                    1975
2        Alaska                 10/1/1994                          0.252                                   1995
3        Arizona                7/17/1994                          0.460                                   1995
4       Arkansas                7/27/1995                          0.433                                   1996
5      California                  N/A                                                                        0
6       Colorado                5/17/2003                          0.627                                   2003
  apply(p_62, 1, str_count, "\\\\s{40,}")
1                                       1
2                                       0
3                                       0
4                                       0
5                                       1
6                                       0
$`|Alabama||1975|N/A|1975`
[1] 0 7 4 3 4

$`|Alaska||10/1/1994||0.252|||1995`
[1] 0 6 9 5 4

$`|Arizona| 7/17/1994||0.460|||1995`
[1]  0  7 10  5  4

$`|Arkansas| 7/27/1995||0.433|||1996`
[1]  0  8 10  5  4

$`|California||N/A|N/A|0`
[1]  0 10  3  3  1

$`|Colorado| 5/17/2003||0.627|||2003`
[1]  0  8 10  5  4

$`|Connecticut||1970|N/A|1970`
[1]  0 11  4  3  4

$`|Delaware||N/A|N/A|0`
[1] 0 8 3 3 1

$`District of Columbia|N/A|N/A|0`
[1] 20  3  3  1

$`|Florida| 10/1/1987||0.252|||1988`
[1]  0  7 10  5  4

$`|Georgia| 8/25/1989||0.353|||1990`
[1]  0  7 10  5  4

$`|Hawaii||N/A|N/A|0`
[1] 0 6 3 3 1

$`|Idaho||7/1/1990||0.504|||1990`
[1] 0 5 8 5 4

$`|Illinois| 1/5/2014|N/A|2014`
[1] 0 8 9 3 4

$`|Indiana| 1/15/1980||0.962|||1980`
[1]  0  7 10  5  4

$`|Iowa||1/1/2011||1.000|||2011`
[1] 0 4 8 5 4

$`|Kansas||1/1/2007||1.000|||2007`
[1] 0 6 8 5 4

$`|Kentucky| 10/1/1996||0.251|||1997`
[1]  0  8 10  5  4

$`|Louisiana|4/19/1996||0.702|||1996`
[1] 0 9 9 5 4

$`|Maine||9/19/1985||0.285|||1986`
[1] 0 5 9 5 4

$`|Maryland||N/A|N/A|0`
[1] 0 8 3 3 1

$`|Massachusetts||N/A|N/A|0`
[1]  0 13  3  3  1

$`|Michigan||7/1/2001||0.504|||2001`
[1] 0 8 8 5 4

$`|Minnesota| 5/28/2003||0.597|||2003`
[1]  0  9 10  5  4

$`|Mississippi|7/1/1990||0.504|||1990`
[1]  0 11  8  5  4

$`|Missouri| 2/26/2004||0.847|||2004`
[1]  0  8 10  5  4

$`|Montana||10/1/1991||0.252|||1992`
[1] 0 7 9 5 4

$`|Nebraska||1/1/2007||1.000|||2007`
[1] 0 8 8 5 4

$`|Nevada||10/1/1995||0.252|||1996`
[1] 0 6 9 5 4

$`|New Hampshire||1959|N/A|1959`
[1]  0 13  4  3  4

$`|New Jersey||N/A|N/A|0`
[1]  0 10  3  3  1

$`|New Mexico||1/1/2004||1.000|||2004`
[1]  0 10  8  5  4

$`|New York||N/A|N/A|0`
[1] 0 8 3 3 1

$`|North Carolina|12/1/1995||0.085|||1996`
[1]  0 14  9  5  4

$`|North Dakota| 8/1/1985||0.419|||1986`
[1]  0 12  9  5  4

$`|Ohio||4/8/2004||0.732|||2004`
[1] 0 4 8 5 4

$`|Oklahoma||1/1/1996||1.000|||1996`
[1] 0 8 8 5 4

$`|Oregon||1/1/1990||1.000|||1990`
[1] 0 6 8 5 4

$`|Pennsylvania|6/17/1989||0.542|||1989`
[1]  0 12  9  5  4

$`|Philadelphia|10/11/1995||0.225|||1996`
[1]  0 12 10  5  4

$`|Rhode Island||N/A|N/A|0`
[1]  0 12  3  3  1

$`|South Carolina|8/23/1996||0.358|||1997`
[1]  0 14  9  5  4

$`|South Dakota| 7/1/1985||0.504|||1985`
[1]  0 12  9  5  4

$`|Tennessee| 10/1/1996||0.251|||1997`
[1]  0  9 10  5  4

$`|Texas||1/1/1996||1.000|||1996`
[1] 0 5 8 5 4

$`|Utah||5/1/1995||0.671|||1995`
[1] 0 4 8 5 4

$`|Vermont||1970|N/A|1970`
[1] 0 7 4 3 4

$`|Virginia| 5/5/1995||0.660|||1995`
[1] 0 8 9 5 4

$`|Washington||1961|N/A|1961`
[1]  0 10  4  3  4

$`|West Virginia|7/7/1989||0.488|||1990`
[1]  0 13  8  5  4

$`|Wisconsin| 11/1/2011||0.167|||2012`
[1]  0  9 10  5  4

$`|Wyoming||10/1/1994||0.252|||1995`
[1] 0 7 9 5 4
 [1] "|Alabama||1975|N/A|1975"                
 [2] "|Alaska||10/1/1994||0.252|||1995"       
 [3] "|Arizona| 7/17/1994||0.460|||1995"      
 [4] "|Arkansas| 7/27/1995||0.433|||1996"     
 [5] "|California||N/A|N/A|0"                 
 [6] "|Colorado| 5/17/2003||0.627|||2003"     
 [7] "|Connecticut||1970|N/A|1970"            
 [8] "|Delaware||N/A|N/A|0"                   
 [9] "District of Columbia|N/A|N/A|0"         
[10] "|Florida| 10/1/1987||0.252|||1988"      
[11] "|Georgia| 8/25/1989||0.353|||1990"      
[12] "|Hawaii||N/A|N/A|0"                     
[13] "|Idaho||7/1/1990||0.504|||1990"         
[14] "|Illinois| 1/5/2014|N/A|2014"           
[15] "|Indiana| 1/15/1980||0.962|||1980"      
[16] "|Iowa||1/1/2011||1.000|||2011"          
[17] "|Kansas||1/1/2007||1.000|||2007"        
[18] "|Kentucky| 10/1/1996||0.251|||1997"     
[19] "|Louisiana|4/19/1996||0.702|||1996"     
[20] "|Maine||9/19/1985||0.285|||1986"        
[21] "|Maryland||N/A|N/A|0"                   
[22] "|Massachusetts||N/A|N/A|0"              
[23] "|Michigan||7/1/2001||0.504|||2001"      
[24] "|Minnesota| 5/28/2003||0.597|||2003"    
[25] "|Mississippi|7/1/1990||0.504|||1990"    
[26] "|Missouri| 2/26/2004||0.847|||2004"     
[27] "|Montana||10/1/1991||0.252|||1992"      
[28] "|Nebraska||1/1/2007||1.000|||2007"      
[29] "|Nevada||10/1/1995||0.252|||1996"       
[30] "|New Hampshire||1959|N/A|1959"          
[31] "|New Jersey||N/A|N/A|0"                 
[32] "|New Mexico||1/1/2004||1.000|||2004"    
[33] "|New York||N/A|N/A|0"                   
[34] "|North Carolina|12/1/1995||0.085|||1996"
[35] "|North Dakota| 8/1/1985||0.419|||1986"  
[36] "|Ohio||4/8/2004||0.732|||2004"          
[37] "|Oklahoma||1/1/1996||1.000|||1996"      
[38] "|Oregon||1/1/1990||1.000|||1990"        
[39] "|Pennsylvania|6/17/1989||0.542|||1989"  
[40] "|Philadelphia|10/11/1995||0.225|||1996" 
[41] "|Rhode Island||N/A|N/A|0"               
[42] "|South Carolina|8/23/1996||0.358|||1997"
[43] "|South Dakota| 7/1/1985||0.504|||1985"  
[44] "|Tennessee| 10/1/1996||0.251|||1997"    
[45] "|Texas||1/1/1996||1.000|||1996"         
[46] "|Utah||5/1/1995||0.671|||1995"          
[47] "|Vermont||1970|N/A|1970"                
[48] "|Virginia| 5/5/1995||0.660|||1995"      
[49] "|Washington||1961|N/A|1961"             
[50] "|West Virginia|7/7/1989||0.488|||1990"  
[51] "|Wisconsin| 11/1/2011||0.167|||2012"    
[52] "|Wyoming||10/1/1994||0.252|||1995"      
              STATE          E_Date_RTC Frac_Yr_Eff_Yr_Pass         RTC_Date_SA 
        "character"         "character"         "character"         "character" 
       STATE RTC_LAW_YEAR 
 "character"    "numeric" 
       STATE RTC_LAW_YEAR
1    Alabama         1975
2     Alaska         1995
3    Arizona         1995
4   Arkansas         1996
5 California          Inf
6   Colorado         2003

Checkpoint

[1] "YEAR"     "STATE"    "VARIABLE" "VALUE"   
[1] "YEAR"     "STATE"    "VARIABLE" "VALUE"   
[1] "STATE"    "YEAR"     "VALUE"    "VARIABLE"
[1] "YEAR"     "STATE"    "VALUE"    "VARIABLE"
[1] "YEAR"     "VALUE"    "STATE"    "VARIABLE"
# A tibble: 6 x 4
   YEAR STATE   VARIABLE                    VALUE
  <dbl> <chr>   <chr>                       <dbl>
1  1977 Alabama Black_Male_15_to_19_years  1.55  
2  1977 Alabama Black_Male_20_to_39_years  3.04  
3  1977 Alabama Other_Male_15_to_19_years  0.0178
4  1977 Alabama Other_Male_20_to_39_years  0.0642
5  1977 Alabama White_Male_15_to_19_years  3.58  
6  1977 Alabama White_Male_20_to_39_years 11.1   
# A tibble: 6 x 4
   YEAR STATE   VARIABLE                       VALUE
  <dbl> <chr>   <chr>                          <dbl>
1  1977 Alabama Black_Female_10_to_19_years     3.01
2  1977 Alabama Black_Female_20_to_29_years     2.33
3  1977 Alabama Black_Female_30_to_39_years     1.29
4  1977 Alabama Black_Female_40_to_49_years     1.18
5  1977 Alabama Black_Female_50_to_64_years     1.73
6  1977 Alabama Black_Female_65_years_and_over  1.58
# A tibble: 6 x 4
  STATE    YEAR VALUE VARIABLE         
  <chr>   <dbl> <dbl> <chr>            
1 Alabama  1977   7.3 Unemployment_rate
2 Alabama  1978   6.4 Unemployment_rate
3 Alabama  1979   7.2 Unemployment_rate
4 Alabama  1980   8.9 Unemployment_rate
5 Alabama  1981  10.6 Unemployment_rate
6 Alabama  1982  14.1 Unemployment_rate
# A tibble: 6 x 4
   YEAR STATE      VALUE VARIABLE    
  <dbl> <chr>      <dbl> <chr>       
1  2018 Alabama     16   Poverty_rate
2  2018 Alaska      13.1 Poverty_rate
3  2018 Arizona     12.8 Poverty_rate
4  2018 Arkansas    15.9 Poverty_rate
5  2018 California  11.9 Poverty_rate
6  2018 Colorado     9.1 Poverty_rate
# A tibble: 6 x 4
   YEAR VALUE STATE   VARIABLE        
  <dbl> <dbl> <chr>   <chr>           
1  1977 15293 Alabama Viol_crime_count
2  1978 15682 Alabama Viol_crime_count
3  1979 15578 Alabama Viol_crime_count
4  1980 17320 Alabama Viol_crime_count
5  1981 18423 Alabama Viol_crime_count
6  1982 17653 Alabama Viol_crime_count

Join

Donohue, et al.

# A tibble: 33 x 2
    YEAR     n
   <dbl> <int>
 1  1980    52
 2  1981    52
 3  1982    52
 4  1983    52
 5  1984    52
 6  1985    52
 7  1986    52
 8  1987    52
 9  1988    52
10  1989    52
11  1990    52
12  1991    52
13  1992    52
14  1993    52
15  1994    52
16  1995    52
17  1996    52
18  1997    52
19  1998    52
20  1999    52
21  2000    52
22  2001    52
23  2002    52
24  2003    52
25  2004    52
26  2005    52
27  2006    52
28  2007    52
29  2008    52
30  2009    52
31  2010    52
32  2011    52
33  2012    52
             Alabama               Alaska              Arizona 
                  44                   44                   44 
            Arkansas           California             Colorado 
                  44                   44                   44 
         Connecticut                 D.C.             Delaware 
                  44                   33                   44 
District of Columbia              Florida              Georgia 
                  44                   44                   44 
              Hawaii                Idaho             Illinois 
                  44                   44                   44 
             Indiana                 Iowa               Kansas 
                  44                   44                   44 
            Kentucky            Louisiana                Maine 
                  44                   44                   44 
            Maryland        Massachusetts             Michigan 
                  44                   44                   44 
           Minnesota          Mississippi             Missouri 
                  44                   44                   44 
             Montana             Nebraska               Nevada 
                  44                   44                   44 
       New Hampshire           New Jersey           New Mexico 
                  44                   44                   44 
            New York       North Carolina         North Dakota 
                  44                   44                   44 
                Ohio             Oklahoma               Oregon 
                  44                   44                   44 
        Pennsylvania         Rhode Island       South Carolina 
                  44                   44                   44 
        South Dakota            Tennessee                Texas 
                  44                   44                   44 
                Utah              Vermont             Virginia 
                  44                   44                   44 
          Washington        West Virginia            Wisconsin 
                  44                   44                   44 
             Wyoming 
                  44 
[1] 44
             Alabama               Alaska              Arizona 
                  44                   44                   44 
            Arkansas           California             Colorado 
                  44                   44                   44 
         Connecticut District of Columbia             Delaware 
                  44                   77                   44 
             Florida              Georgia               Hawaii 
                  44                   44                   44 
               Idaho             Illinois              Indiana 
                  44                   44                   44 
                Iowa               Kansas             Kentucky 
                  44                   44                   44 
           Louisiana                Maine             Maryland 
                  44                   44                   44 
       Massachusetts             Michigan            Minnesota 
                  44                   44                   44 
         Mississippi             Missouri              Montana 
                  44                   44                   44 
            Nebraska               Nevada        New Hampshire 
                  44                   44                   44 
          New Jersey           New Mexico             New York 
                  44                   44                   44 
      North Carolina         North Dakota                 Ohio 
                  44                   44                   44 
            Oklahoma               Oregon         Pennsylvania 
                  44                   44                   44 
        Rhode Island       South Carolina         South Dakota 
                  44                   44                   44 
           Tennessee                Texas                 Utah 
                  44                   44                   44 
             Vermont             Virginia           Washington 
                  44                   44                   44 
       West Virginia            Wisconsin              Wyoming 
                  44                   44                   44 
[1] 51
             Alabama               Alaska              Arizona 
                  31                   31                   31 
            Arkansas           California             Colorado 
                  31                   31                   31 
         Connecticut District of Columbia             Delaware 
                  31                   31                   31 
             Florida              Georgia               Hawaii 
                  31                   31                   31 
               Idaho             Illinois              Indiana 
                  31                   31                   31 
                Iowa               Kansas             Kentucky 
                  31                   31                   31 
           Louisiana                Maine             Maryland 
                  31                   31                   31 
       Massachusetts             Michigan            Minnesota 
                  31                   31                   31 
         Mississippi             Missouri              Montana 
                  31                   31                   31 
            Nebraska               Nevada        New Hampshire 
                  31                   31                   31 
          New Jersey           New Mexico             New York 
                  31                   31                   31 
      North Carolina         North Dakota                 Ohio 
                  31                   31                   31 
            Oklahoma               Oregon         Pennsylvania 
                  31                   31                   31 
        Rhode Island       South Carolina         South Dakota 
                  31                   31                   31 
           Tennessee                Texas                 Utah 
                  31                   31                   31 
             Vermont             Virginia           Washington 
                  31                   31                   31 
       West Virginia            Wisconsin              Wyoming 
                  31                   31                   31 
              Alaska              Arizona             Arkansas 
                  31                   31                   31 
          California             Colorado District of Columbia 
                  31                   31                   31 
            Delaware              Florida              Georgia 
                  31                   31                   31 
              Hawaii                Idaho             Illinois 
                  31                   31                   31 
                Iowa               Kansas             Kentucky 
                  31                   31                   31 
           Louisiana                Maine             Maryland 
                  31                   31                   31 
       Massachusetts             Michigan            Minnesota 
                  31                   31                   31 
         Mississippi             Missouri              Montana 
                  31                   31                   31 
            Nebraska               Nevada           New Jersey 
                  31                   31                   31 
          New Mexico             New York       North Carolina 
                  31                   31                   31 
        North Dakota                 Ohio             Oklahoma 
                  31                   31                   31 
              Oregon         Pennsylvania         Rhode Island 
                  31                   31                   31 
      South Carolina         South Dakota            Tennessee 
                  31                   31                   31 
               Texas                 Utah             Virginia 
                  31                   31                   31 
       West Virginia            Wisconsin              Wyoming 
                  31                   31                   31 
[1] 45

Lott and Mustard

# A tibble: 33 x 2
    YEAR     n
   <dbl> <int>
 1  1980    52
 2  1981    52
 3  1982    52
 4  1983    52
 5  1984    52
 6  1985    52
 7  1986    52
 8  1987    52
 9  1988    52
10  1989    52
11  1990    52
12  1991    52
13  1992    52
14  1993    52
15  1994    52
16  1995    52
17  1996    52
18  1997    52
19  1998    52
20  1999    52
21  2000    52
22  2001    52
23  2002    52
24  2003    52
25  2004    52
26  2005    52
27  2006    52
28  2007    52
29  2008    52
30  2009    52
31  2010    52
32  2011    52
33  2012    52
             Alabama               Alaska              Arizona 
                  44                   44                   44 
            Arkansas           California             Colorado 
                  44                   44                   44 
         Connecticut                 D.C.             Delaware 
                  44                   33                   44 
District of Columbia              Florida              Georgia 
                  44                   44                   44 
              Hawaii                Idaho             Illinois 
                  44                   44                   44 
             Indiana                 Iowa               Kansas 
                  44                   44                   44 
            Kentucky            Louisiana                Maine 
                  44                   44                   44 
            Maryland        Massachusetts             Michigan 
                  44                   44                   44 
           Minnesota          Mississippi             Missouri 
                  44                   44                   44 
             Montana             Nebraska               Nevada 
                  44                   44                   44 
       New Hampshire           New Jersey           New Mexico 
                  44                   44                   44 
            New York       North Carolina         North Dakota 
                  44                   44                   44 
                Ohio             Oklahoma               Oregon 
                  44                   44                   44 
        Pennsylvania         Rhode Island       South Carolina 
                  44                   44                   44 
        South Dakota            Tennessee                Texas 
                  44                   44                   44 
                Utah              Vermont             Virginia 
                  44                   44                   44 
          Washington        West Virginia            Wisconsin 
                  44                   44                   44 
             Wyoming 
                  44 
[1] 44
             Alabama               Alaska              Arizona 
                  44                   44                   44 
            Arkansas           California             Colorado 
                  44                   44                   44 
         Connecticut District of Columbia             Delaware 
                  44                   77                   44 
             Florida              Georgia               Hawaii 
                  44                   44                   44 
               Idaho             Illinois              Indiana 
                  44                   44                   44 
                Iowa               Kansas             Kentucky 
                  44                   44                   44 
           Louisiana                Maine             Maryland 
                  44                   44                   44 
       Massachusetts             Michigan            Minnesota 
                  44                   44                   44 
         Mississippi             Missouri              Montana 
                  44                   44                   44 
            Nebraska               Nevada        New Hampshire 
                  44                   44                   44 
          New Jersey           New Mexico             New York 
                  44                   44                   44 
      North Carolina         North Dakota                 Ohio 
                  44                   44                   44 
            Oklahoma               Oregon         Pennsylvania 
                  44                   44                   44 
        Rhode Island       South Carolina         South Dakota 
                  44                   44                   44 
           Tennessee                Texas                 Utah 
                  44                   44                   44 
             Vermont             Virginia           Washington 
                  44                   44                   44 
       West Virginia            Wisconsin              Wyoming 
                  44                   44                   44 
[1] 51
             Alabama               Alaska              Arizona 
                  31                   31                   31 
            Arkansas           California             Colorado 
                  31                   31                   31 
         Connecticut District of Columbia             Delaware 
                  31                   31                   31 
             Florida              Georgia               Hawaii 
                  31                   31                   31 
               Idaho             Illinois              Indiana 
                  31                   31                   31 
                Iowa               Kansas             Kentucky 
                  31                   31                   31 
           Louisiana                Maine             Maryland 
                  31                   31                   31 
       Massachusetts             Michigan            Minnesota 
                  31                   31                   31 
         Mississippi             Missouri              Montana 
                  31                   31                   31 
            Nebraska               Nevada        New Hampshire 
                  31                   31                   31 
          New Jersey           New Mexico             New York 
                  31                   31                   31 
      North Carolina         North Dakota                 Ohio 
                  31                   31                   31 
            Oklahoma               Oregon         Pennsylvania 
                  31                   31                   31 
        Rhode Island       South Carolina         South Dakota 
                  31                   31                   31 
           Tennessee                Texas                 Utah 
                  31                   31                   31 
             Vermont             Virginia           Washington 
                  31                   31                   31 
       West Virginia            Wisconsin              Wyoming 
                  31                   31                   31 
              Alaska              Arizona             Arkansas 
                  31                   31                   31 
          California             Colorado District of Columbia 
                  31                   31                   31 
            Delaware              Florida              Georgia 
                  31                   31                   31 
              Hawaii                Idaho             Illinois 
                  31                   31                   31 
                Iowa               Kansas             Kentucky 
                  31                   31                   31 
           Louisiana                Maine             Maryland 
                  31                   31                   31 
       Massachusetts             Michigan            Minnesota 
                  31                   31                   31 
         Mississippi             Missouri              Montana 
                  31                   31                   31 
            Nebraska               Nevada           New Jersey 
                  31                   31                   31 
          New Mexico             New York       North Carolina 
                  31                   31                   31 
        North Dakota                 Ohio             Oklahoma 
                  31                   31                   31 
              Oregon         Pennsylvania         Rhode Island 
                  31                   31                   31 
      South Carolina         South Dakota            Tennessee 
                  31                   31                   31 
               Texas                 Utah             Virginia 
                  31                   31                   31 
       West Virginia            Wisconsin              Wyoming 
                  31                   31                   31 
[1] 45

Data Exploration


                    STATE                      YEAR Black_Male_15_to_19_years 
                 "factor"                 "numeric"                 "numeric" 
Black_Male_20_to_39_years Other_Male_15_to_19_years Other_Male_20_to_39_years 
                "numeric"                 "numeric"                 "numeric" 
White_Male_15_to_19_years White_Male_20_to_39_years         Unemployment_rate 
                "numeric"                 "numeric"                 "numeric" 
             Poverty_rate          Viol_crime_count                Population 
                "numeric"                 "numeric"                 "numeric" 
      police_per_100k_lag              RTC_LAW_YEAR                   RTC_LAW 
                "numeric"                 "numeric"                 "logical" 
                   TIME_0                  TIME_INF        Viol_crime_rate_1k 
                "numeric"                 "numeric"                 "numeric" 
   Viol_crime_rate_1k_log            Population_log 
                "numeric"                 "numeric" 

Data Analysis


Donohue, et al.

Some code taken from http://karthur.org/2019/implementing-fixed-effects-panel-models-in-r.html

Twoways effects Within Model

Call:
plm(formula = Viol_crime_rate_1k_log ~ RTC_LAW + White_Male_15_to_19_years + 
    White_Male_20_to_39_years + Black_Male_15_to_19_years + Black_Male_20_to_39_years + 
    Other_Male_15_to_19_years + Other_Male_20_to_39_years + Unemployment_rate + 
    Poverty_rate + Population_log + police_per_100k_lag, data = d_panel_DONOHUE, 
    effect = "twoways", model = "within")

Balanced Panel: n = 45, T = 31, N = 1395

Residuals:
       Min.     1st Qu.      Median     3rd Qu.        Max. 
-0.57957437 -0.08942194 -0.00090654  0.08673054  1.11216999 

Coefficients:
                             Estimate  Std. Error t-value  Pr(>|t|)    
RTC_LAWTRUE                0.01796779  0.01663911  1.0799 0.2804066    
White_Male_15_to_19_years -0.00091825  0.02724210 -0.0337 0.9731160    
White_Male_20_to_39_years  0.03466473  0.00972839  3.5633 0.0003794 ***
Black_Male_15_to_19_years -0.05673593  0.05746052 -0.9874 0.3236341    
Black_Male_20_to_39_years  0.12605439  0.01931450  6.5264 9.607e-11 ***
Other_Male_15_to_19_years  0.69201638  0.11322394  6.1119 1.297e-09 ***
Other_Male_20_to_39_years -0.30276797  0.03811855 -7.9428 4.226e-15 ***
Unemployment_rate         -0.01685806  0.00489952 -3.4408 0.0005984 ***
Poverty_rate              -0.00780235  0.00295720 -2.6384 0.0084280 ** 
Population_log            -0.17991653  0.06041773 -2.9779 0.0029559 ** 
police_per_100k_lag        0.00060391  0.00013689  4.4115 1.111e-05 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Total Sum of Squares:    43.211
Residual Sum of Squares: 36.716
R-Squared:      0.15031
Adj. R-Squared: 0.095138
F-statistic: 21.0514 on 11 and 1309 DF, p-value: < 2.22e-16

Lott and Mustard

Some code taken from http://karthur.org/2019/implementing-fixed-effects-panel-models-in-r.html

Twoways effects Within Model

Call:
plm(formula = LOTT_fmla, data = d_panel_LOTT, effect = "twoways", 
    model = "within")

Balanced Panel: n = 45, T = 31, N = 1395

Residuals:
      Min.    1st Qu.     Median    3rd Qu.       Max. 
-0.5448906 -0.0780395  0.0026738  0.0788052  0.5847263 

Coefficients:
                                  Estimate  Std. Error  t-value  Pr(>|t|)    
RTC_LAWTRUE                    -0.04687169  0.01641851  -2.8548 0.0043758 ** 
White_Female_10_to_19_years     0.62441376  0.15103427   4.1343 3.793e-05 ***
White_Female_20_to_29_years    -0.05942541  0.06332108  -0.9385 0.3481763    
White_Female_30_to_39_years     0.16028113  0.08045953   1.9921 0.0465755 *  
White_Female_40_to_49_years     0.10087510  0.08170707   1.2346 0.2172082    
White_Female_50_to_64_years    -0.37624966  0.06303172  -5.9692 3.083e-09 ***
White_Female_65_years_and_over  0.20636690  0.04742430   4.3515 1.460e-05 ***
White_Male_10_to_19_years      -0.59141591  0.14436974  -4.0965 4.457e-05 ***
White_Male_20_to_29_years       0.08717546  0.05862342   1.4870 0.1372503    
White_Male_30_to_39_years      -0.12514225  0.08588569  -1.4571 0.1453400    
White_Male_40_to_49_years      -0.21812366  0.07293615  -2.9906 0.0028375 ** 
White_Male_50_to_64_years       0.37845575  0.07314122   5.1743 2.653e-07 ***
White_Male_65_years_and_over   -0.20915907  0.06659815  -3.1406 0.0017246 ** 
Black_Female_10_to_19_years    -1.03146594  0.43610403  -2.3652 0.0181697 *  
Black_Female_20_to_29_years    -0.02721685  0.17462559  -0.1559 0.8761693    
Black_Female_30_to_39_years    -0.03246043  0.20498789  -0.1584 0.8742037    
Black_Female_40_to_49_years     0.43820099  0.23524130   1.8628 0.0627234 .  
Black_Female_50_to_64_years     0.04906111  0.21393128   0.2293 0.8186482    
Black_Female_65_years_and_over  0.07226074  0.24373031   0.2965 0.7669130    
Black_Male_10_to_19_years       1.22536162  0.44559642   2.7499 0.0060447 ** 
Black_Male_20_to_29_years      -0.06587312  0.18392655  -0.3581 0.7202909    
Black_Male_30_to_39_years       0.24720746  0.23673862   1.0442 0.2965804    
Black_Male_40_to_49_years      -0.66869983  0.27173041  -2.4609 0.0139904 *  
Black_Male_50_to_64_years      -0.16737616  0.23977741  -0.6980 0.4852740    
Black_Male_65_years_and_over   -0.58743446  0.34691532  -1.6933 0.0906404 .  
Other_Female_10_to_19_years     0.70957924  0.49539878   1.4323 0.1522910    
Other_Female_20_to_29_years    -1.16489945  0.26997487  -4.3148 1.720e-05 ***
Other_Female_30_to_39_years    -3.40258912  0.35368437  -9.6204 < 2.2e-16 ***
Other_Female_40_to_49_years     1.34563633  0.42503994   3.1659 0.0015825 ** 
Other_Female_50_to_64_years     2.93990932  0.33830653   8.6901 < 2.2e-16 ***
Other_Female_65_years_and_over  2.36026239  0.20422580  11.5571 < 2.2e-16 ***
Other_Male_10_to_19_years       0.07481449  0.47835310   0.1564 0.8757423    
Other_Male_20_to_29_years       1.62895925  0.25740603   6.3284 3.420e-10 ***
Other_Male_30_to_39_years       3.17421278  0.41184489   7.7073 2.566e-14 ***
Other_Male_40_to_49_years      -1.58494177  0.44840281  -3.5346 0.0004229 ***
Other_Male_50_to_64_years      -3.91523867  0.37399898 -10.4686 < 2.2e-16 ***
Other_Male_65_years_and_over   -4.16596244  0.36860536 -11.3020 < 2.2e-16 ***
Unemployment_rate              -0.00545734  0.00436374  -1.2506 0.2113054    
Poverty_rate                   -0.00572362  0.00253162  -2.2609 0.0239357 *  
Population_log                 -0.21716335  0.08452664  -2.5692 0.0103068 *  
police_per_100k_lag             0.00069547  0.00013331   5.2171 2.118e-07 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Total Sum of Squares:    43.211
Residual Sum of Squares: 23.647
R-Squared:      0.45275
Adj. R-Squared: 0.40355
F-statistic: 25.8088 on 41 and 1279 DF, p-value: < 2.22e-16

Multicollinearity analysis

How did the above happen?

The analysis dataframes are very similar yet rendered very different results.

- different number of columns: 20 vs 50
[1] TRUE

The only difference between the two dataframes rests in how the demographic variables were parameterized.

[1] "Black_Male_15_to_19_years" "Black_Male_20_to_39_years"
[3] "Other_Male_15_to_19_years" "Other_Male_20_to_39_years"
[5] "White_Male_15_to_19_years" "White_Male_20_to_39_years"
 [1] "Black_Female_10_to_19_years"    "Black_Female_20_to_29_years"   
 [3] "Black_Female_30_to_39_years"    "Black_Female_40_to_49_years"   
 [5] "Black_Female_50_to_64_years"    "Black_Female_65_years_and_over"
 [7] "Black_Male_10_to_19_years"      "Black_Male_20_to_29_years"     
 [9] "Black_Male_30_to_39_years"      "Black_Male_40_to_49_years"     
[11] "Black_Male_50_to_64_years"      "Black_Male_65_years_and_over"  
[13] "Other_Female_10_to_19_years"    "Other_Female_20_to_29_years"   
[15] "Other_Female_30_to_39_years"    "Other_Female_40_to_49_years"   
[17] "Other_Female_50_to_64_years"    "Other_Female_65_years_and_over"
[19] "Other_Male_10_to_19_years"      "Other_Male_20_to_29_years"     
[21] "Other_Male_30_to_39_years"      "Other_Male_40_to_49_years"     
[23] "Other_Male_50_to_64_years"      "Other_Male_65_years_and_over"  
[25] "White_Female_10_to_19_years"    "White_Female_20_to_29_years"   
[27] "White_Female_30_to_39_years"    "White_Female_40_to_49_years"   
[29] "White_Female_50_to_64_years"    "White_Female_65_years_and_over"
[31] "White_Male_10_to_19_years"      "White_Male_20_to_29_years"     
[33] "White_Male_30_to_39_years"      "White_Male_40_to_49_years"     
[35] "White_Male_50_to_64_years"      "White_Male_65_years_and_over"  

Clearly, this had an effect on the results of the analysis.

Let’s explore how this occured.

When seemingly independent variables are highly related to one another, the relationships estimated in an analysis may be distorted.

In regression analysis, this distortion is often a byproduct of a violation of the independence assumption. This distortion, if large enough, can impact statistical inference.

There are several ways we can diagnose multicollinearity.

Correlation

Again, multicollinearity often occurs when independent variables are highly related to one another. Consequently, we can evaluate these relationships be examining the correlation between variable pairs.

It is important to note that multicollinearity and correlation are not one and the same. Correlation can be thought of as the strength of the relationship between variables. On the other hand, multicollinearity can be thought of the the violation of the independence assumption that is a consequence of this correlation in a regression analysis.

Scatterplots

 [1] "STATE"                     "YEAR"                     
 [3] "Black_Male_15_to_19_years" "Black_Male_20_to_39_years"
 [5] "Other_Male_15_to_19_years" "Other_Male_20_to_39_years"
 [7] "White_Male_15_to_19_years" "White_Male_20_to_39_years"
 [9] "Unemployment_rate"         "Poverty_rate"             
[11] "Viol_crime_count"          "Population"               
[13] "police_per_100k_lag"       "RTC_LAW_YEAR"             
[15] "RTC_LAW"                   "TIME_0"                   
[17] "TIME_INF"                  "Viol_crime_rate_1k"       
[19] "Viol_crime_rate_1k_log"    "Population_log"           

Coefficient estimate instability

sims <- 250

# DONOHUE

# round(dim(DONOHUE_DF)[1]/2)
samps_DONOHUE <- lapply(rep(dim(DONOHUE_DF)[1]-1, sims),
       function(x)DONOHUE_DF[sample(nrow(DONOHUE_DF),
                                     size = x, replace = FALSE),])

fit_nls_on_bootstrap_DONOHUE <- function(split){
  plm(Viol_crime_rate_1k_log ~
                        RTC_LAW +
                        White_Male_15_to_19_years +
                        White_Male_20_to_39_years +
                        Black_Male_15_to_19_years +
                        Black_Male_20_to_39_years +
                        Other_Male_15_to_19_years +
                        Other_Male_20_to_39_years +
                        Unemployment_rate +
                        Poverty_rate + 
                        Population_log + 
                        police_per_100k_lag,
      data = data.frame(split),
      index = c("STATE","YEAR"),
      model = "within",
      effect = "twoways")
}
  
samps_models_DONOHUE <- lapply(samps_DONOHUE, fit_nls_on_bootstrap_DONOHUE)

samps_models_DONOHUE <- samps_models_DONOHUE %>%
  map(tidy)

names(samps_models_DONOHUE) <- paste0("DONOHUE_",1:length(samps_models_DONOHUE))

simulations_DONOHUE <- samps_models_DONOHUE %>%
  bind_rows(.id = "ID") %>%
  mutate(Analysis = "Analysis 1")

## LOTT

samps_LOTT <- lapply(rep(round(dim(LOTT_DF)[1]/2), sims),
       function(x) LOTT_DF[sample(nrow(LOTT_DF),
                                  size = x, replace = FALSE),])

fit_nls_on_bootstrap_LOTT <- function(split){
  plm(LOTT_fmla,
      data = data.frame(split),
      index = c("STATE","YEAR"),
      model = "within",
      effect = "twoways")
}
  
samps_models_LOTT <- lapply(samps_LOTT, fit_nls_on_bootstrap_LOTT)

samps_models_LOTT <- samps_models_LOTT %>%
  map(tidy)

names(samps_models_LOTT) <- paste0("LOTT_",1:length(samps_models_LOTT))

simulations_LOTT <- samps_models_LOTT %>%
  bind_rows(.id = "Analysis") %>%
  mutate(Analysis = "Analysis 2")

simulations <- bind_rows(simulations_DONOHUE,
                         simulations_LOTT)

simulation_plot <- simulations %>%
  filter(term=="RTC_LAWTRUE") %>%
  ggplot(aes(x = Analysis, y = estimate)) + 
  geom_jitter(alpha = 0.25,
              width = 0.1) + 
  labs(title = "Coefficient instability",
       subtitle = "Estimates sensitive to observation deletions",
       x = "Term",
       y = "Coefficient",
       caption = "Results from simulations") + 
  theme_minimal() +
  theme(axis.title.x = element_blank())

simulation_plot

VIF

              RTC_LAWTRUE White_Male_15_to_19_years White_Male_20_to_39_years 
                 1.097853                  1.172339                  1.738459 
Black_Male_15_to_19_years Black_Male_20_to_39_years Other_Male_15_to_19_years 
                 1.344193                  1.653712                  1.586648 
Other_Male_20_to_39_years         Unemployment_rate              Poverty_rate 
                 1.529688                  1.244667                  1.270321 
           Population_log       police_per_100k_lag 
                 1.153933                  1.204491 
                   RTC_LAWTRUE    White_Female_10_to_19_years 
                      1.621662                     127.920555 
   White_Female_20_to_29_years    White_Female_30_to_39_years 
                     42.269637                      49.635014 
   White_Female_40_to_49_years    White_Female_50_to_64_years 
                     37.550101                      36.451868 
White_Female_65_years_and_over      White_Male_10_to_19_years 
                     12.866751                     126.824984 
     White_Male_20_to_29_years      White_Male_30_to_39_years 
                     39.248785                      73.008959 
     White_Male_40_to_49_years      White_Male_50_to_64_years 
                     31.613855                      52.774694 
  White_Male_65_years_and_over    Black_Female_10_to_19_years 
                     13.285326                     335.136906 
   Black_Female_20_to_29_years    Black_Female_30_to_39_years 
                    106.644486                      79.058455 
   Black_Female_40_to_49_years    Black_Female_50_to_64_years 
                     98.434064                      66.888057 
Black_Female_65_years_and_over      Black_Male_10_to_19_years 
                     49.715869                     320.740453 
     Black_Male_20_to_29_years      Black_Male_30_to_39_years 
                     89.297151                      89.267356 
     Black_Male_40_to_49_years      Black_Male_50_to_64_years 
                     92.498486                      64.538516 
  Black_Male_65_years_and_over    Other_Female_10_to_19_years 
                     37.960126                     142.283700 
   Other_Female_20_to_29_years    Other_Female_30_to_39_years 
                     64.966861                      54.511835 
   Other_Female_40_to_49_years    Other_Female_50_to_64_years 
                    224.567085                     131.463113 
Other_Female_65_years_and_over      Other_Male_10_to_19_years 
                     82.394398                     151.930450 
     Other_Male_20_to_29_years      Other_Male_30_to_39_years 
                     54.620045                      62.267344 
     Other_Male_40_to_49_years      Other_Male_50_to_64_years 
                    244.698473                     174.184553 
  Other_Male_65_years_and_over              Unemployment_rate 
                     53.532299                       1.497864 
                  Poverty_rate                 Population_log 
                      1.412397                       3.426475 
           police_per_100k_lag 
                      1.732745 
[1] 1.738459
[1] 335.1369

\[\frac{1}{1-R_{i}^{2}}\]

Synthesis

Data Visualization


Summary


Suggested Homework


LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXM6IEV4YW1pbmF0aW9uIG9mIE11bHRpY29sbGluZWFyaXR5IEluZmx1ZW5jZSBvbiBJbmZlcmVuY2UgVXNpbmcgUmlnaHQtdG8tQ2FycnkgR3VuIExhdyBhbmQgVmlvbGVudCBDcmltZSBEYXRhIgphdXRob3I6ICJNaWNoYWVsIE9udGl2ZXJvcywgQ2FycmllIFdyaWdodCwgUGhELiIKY3NzOiBzdHlsZS5jc3MKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBzZWxmX2NvbnRhaW5lZDogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgo8c3R5bGU+CiNUT0MgewogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL2ltZy9sb2dvLmpwZyIpOwogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsKICBwYWRkaW5nLXRvcDogMjQwcHggIWltcG9ydGFudDsKICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Owp9Cjwvc3R5bGU+CgoKLS0tCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NywKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCiMjIyMgey5vdXRsaW5lIH0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJtYWlucGxvdC5wbmciKSkKYGBgCgojIyMjCgojIyB7LmRpc2NsYWltZXJfYmxvY2t9CgoqKkRpc2NsYWltZXIqKjogVGhlIHB1cnBvc2Ugb2YgdGhlIFtPcGVuIENhc2UgU3R1ZGllc10oaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvKXt0YXJnZXQ9Il9ibGFuayJ9IHByb2plY3QgaXMgKip0byBkZW1vbnN0cmF0ZSB0aGUgdXNlIG9mIHZhcmlvdXMgZGF0YSBzY2llbmNlIG1ldGhvZHMsIHRvb2xzLCBhbmQgc29mdHdhcmUgaW4gdGhlIGNvbnRleHQgb2YgbWVzc3ksIHJlYWwtd29ybGQgZGF0YSoqLiBBIGdpdmVuIGNhc2Ugc3R1ZHkgZG9lcyBub3QgY292ZXIgYWxsIGFzcGVjdHMgb2YgdGhlIHJlc2VhcmNoIHByb2Nlc3MsIGlzIG5vdCBjbGFpbWluZyB0byBiZSB0aGUgbW9zdCBhcHByb3ByaWF0ZSB3YXkgdG8gYW5hbHl6ZSBhIGdpdmVuIGRhdGEgc2V0LCBhbmQgc2hvdWxkIG5vdCBiZSB1c2VkIGluIHRoZSBjb250ZXh0IG9mIG1ha2luZyBwb2xpY3kgZGVjaXNpb25zIHdpdGhvdXQgZXh0ZXJuYWwgY29uc3VsdGF0aW9uIGZyb20gc2NpZW50aWZpYyBleHBlcnRzLiAKCiMjIHsubGlzY2VuY2VfYmxvY2t9CgpUaGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgdGhlIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgWyhDQyBCWS1OQyAzLjApXShodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL3VzLyl7dGFyZ2V0PSJfYmxhbmsifSAgVW5pdGVkIFN0YXRlcyBMaWNlbnNlLgoKIyAqKk1vdGl2YXRpb24qKgoqKiogCgpUaGlzIGNhc2Ugc3R1ZHkgd2lsbCBpbnRyb2R1Y2UgdGhlIHRvcGljIG9mIG11bHRpY29saW5lYXJpdHkuIFdlIHdpbGwgZG8gc28gYnkgc2hvd2Nhc2luZyBhIHJlYWwgd29ybGQgZXhhbXBsZSB3aGVyZSBtdWx0aWNvbGluZWFyaXR5IGluIHBhcnQgcmVzdWx0ZWQgaW4gaGlzdG9yaWNhbGx5IGNvbnRyaXZlcnNpYWwgYW5kIGNvbmZsaWN0aW5nIGZpbmRpbmdzIGFib3V0IHRoZSBpbmZsdWVuY2Ugb2YgdGhlIGFkb3B0aW9uIG9mIHJpZ2h0LXRvLWNhcnJ5IChSVEMpIGNvbmNlYWxlZCBoYW5kZ3VuIGxhd3Mgb24gdmlvbGVudCBjcmltZSByYXRlcyBpbiB0aGUgVW5pdGVkIFN0YXRlcy4gCgpXZSB3aWxsIGZvY3VzIG9uIHR3byBhcnRpY2xlczoKCjEpIFRoZSBmaXJzdCBhbmFseXNpcyBieSBbTG90dCBhbmQgTXVzdGFyZF0oaHR0cHM6Ly9jaGljYWdvdW5ib3VuZC51Y2hpY2Fnby5lZHUvY2dpL3ZpZXdjb250ZW50LmNnaT9hcnRpY2xlPTExNTAmY29udGV4dD1sYXdfYW5kX2Vjb25vbWljcyl7dGFyZ2V0PSJfYmxhbmsifSBwdWJsaXNoZWQgaW4gMTk5NiBzdWdnZXN0cyB0aGF0IFJUQyBsYXdzIHJlZHVjZSB2aW9sZW50IGNyaW1lLiBMb3R0IGF1dGhvcmVkIGEgYm9vayBleHRlbmRpbmcgdGhlc2UgZmluZGluZ3MgaW4gMTk5OCBjYWxsZWQgWyoqKk1vcmUgR3VucywgTGVzcyBDcmltZSoqKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTW9yZV9HdW5zLF9MZXNzX0NyaW1lKXt0YXJnZXQ9Il9ibGFuayJ9LgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC5oZWlnaHQgPSAnMTAwJScsIG91dC53aWR0aCA9ICcxMDAlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCJpbWciLCAiTG90dC5wbmciKSkKYGBgCgoyKSBUaGUgc2Vjb25kIGFuYWx5c2lzIGlzIGEgcmVjZW50IGFydGljbGUgYnkgW0Rvbm9odWUsIGV0IGFsLl0oaHR0cHM6Ly93d3cubmJlci5vcmcvcGFwZXJzL3cyMzUxMC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gcHVibGlzaGVkIGluIDIwMTcgdGhhdCBzdWdnZXN0cyB0aGF0IFJUQyBsYXdzIGluY3JlYXNlIHZpb2xlbnQgY3JpbWUuIERvbm9odWUgaGFzIGFsc28gcHVibGlzaGVkIHByZXZpb3VzIGFydGljbGVzIHdpdGggdGl0bGVzIHN1Y2ggYXMgWyoqKiJTaG9vdGluZyBkb3duIHRoZSAiTW9yZSBHdW5zLCBMZXNzIENyaW1lIiBIeXBvdGhlc2lzKioqXShodHRwczovL3d3dy5qc3Rvci5vcmcvc3RhYmxlLzEyMjk2MDM/c2VxPTEpe3RhcmdldD0iX2JsYW5rIn0gCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LmhlaWdodCA9ICcxMDAlJywgb3V0LndpZHRoID0gJzEwMCUnLCBmaWcuYWxpZ249J2NlbnRlcid9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoImltZyIsICJEb25vaHVlLnBuZyIpKQpgYGAKClRoaXMgaGFzIGJlZW4gYSBjb250cm92ZXJzaWFsIHRvcGljIGFzIG1hbnkgb3RoZXIgYXJ0aWNsZXMgYWxzbyBoYWQgY29uZmxpY3RpbmcgcmVzdWx0cy4gU2VlIFtoZXJlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Nb3JlX0d1bnMsX0xlc3NfQ3JpbWUpe3RhcmdldD0iX2JsYW5rIn0gZm9yIGEgbGlzdCBvZiBzdHVkaWVzLgoKVGhlIFtEb25vaHVlLCBldCBhbC5dKGh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGFydGljbGUgZGlzY3Vzc2VzIGhvdyB0aGVyZSBhcmUgbWFueSBvdGhlciBpbXBvcnRhbnQgbWV0aG9kb2xpY2FsIGFzcGVjdHMgYmVzaWRlcyBtdWx0aWNvbGluZWFyaXR5IHRoYXQgY291bGQgYWNjb3VudCBmb3IgdGhlIGhpc3RvcmljYWxseSBjb25mbGljdGluZyByZXN1bHRzIGluIHRoZXNlIHByZXZpb3VzIHBhcGVycy4KCkluIGZhY3QsIG5lYXJseSBldmVyeSBhc3BlY3Qgb2YgdGhlIGRhdGEgYW5hbHlzaXMgcHJvY2VzcyB3YXMgZGlmZmVyZW50IGJldHdlZW4gdGhlIFtEb25vaHVlLCBldCBhbC5dKGh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGFuYWx5c2lzIGFuZCB0aGUgW0xvdHQgYW5kIE11c3RhcmRdKGh0dHBzOi8vY2hpY2Fnb3VuYm91bmQudWNoaWNhZ28uZWR1L2NnaS92aWV3Y29udGVudC5jZ2k/YXJ0aWNsZT0xMTUwJmNvbnRleHQ9bGF3X2FuZF9lY29ub21pY3Mpe3RhcmdldD0iX2JsYW5rIn0gYW5hbHlzaXMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LmhlaWdodCA9ICc3NSUnLCBvdXQud2lkdGggPSAnNzUlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCJpbWciLCAiRWR1Y2F0aW9uYWxfR3JhcGhpYzEuanBnIikpCmBgYAoKSG93ZXZlciwgd2Ugd2lsbCBmb2N1cyBwYXJ0aWN1bGFybHkgb24gbXVsdGljb2xpbmVhcml0eSBhbmQgd2Ugd2lsbCBleHBsb3JlIGhvdyBpdCBjYW4gaW5mbHVlbmNlIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2VzIGFuZCByZXN1bHQgaW4gZGlmZmVyZW50IGNvbmNsdXNpb25zLiAKClRoaXMgYW5hbHlzaXMgd2lsbCBkZW1vbnN0cmF0ZSBob3cgbWV0aG9kb2xvZ2ljYWwgZGV0YWlscyBjYW4gYmUgY3JpdGljYWxseSBpbmZsdWVudGlhbCBmb3Igb3VyIG92ZXJhbGwgY29uY2x1c2lvbnMgYW5kIGNhbiByZXN1bHQgaW4gaW1wb3J0YW50IHBvbGljeSByZWxhdGVkIGNvbnNlcXVlbmNlcy4gVGhpcyBbYXJ0aWNsZV0oKGh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9KSB3aWxsIHByb3ZpZGUgYSBiYXNpcyBmb3IgdGhlIG1vdGl2YXRpb24uIAoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KCkpvaG4gSi4gRG9ub2h1ZSBldCBhbC4sIFJpZ2h04oCQdG/igJBDYXJyeSBMYXdzIGFuZCBWaW9sZW50IENyaW1lOiBBIENvbXByZWhlbnNpdmUgQXNzZXNzbWVudCBVc2luZyBQYW5lbCBEYXRhIGFuZCBhIFN0YXRl4oCQTGV2ZWwgU3ludGhldGljIENvbnRyb2wgQW5hbHlzaXMuICpKb3VybmFsIG9mIEVtcGlyaWNhbCBMZWdhbCBTdHVkaWVzKiwgMTYsMiAoMjAxOSkuCgpEYXZpZCBCLiBNdXN0YXJkICYgSm9obiBMb3R0LiBDcmltZSwgRGV0ZXJyZW5jZSwgYW5kIFJpZ2h0LXRvLUNhcnJ5IENvbmNlYWxlZCBIYW5kZ3Vucy4gKkNvYXNlLVNhbmRvciBJbnN0aXR1dGUgZm9yIExhdyAmIEVjb25vbWljcyogV29ya2luZyBQYXBlciBOby4gNDEsICgxOTk2KS4KCiMjIyMKCgpIZXJlIHlvdSBjYW4gc2VlIHRoZSBkaWZmZXJlbmNlcyBpbiB0aGUgZGF0YSB1c2VkIGluIHRoZSBmZWF0dXJlZCBSVEMgYXJ0aWNsZXM6CgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC5oZWlnaHQgPSAnMTAwJScsIG91dC53aWR0aCA9ICcxMDAlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCJpbWciLCdEb25vaHVlX1RhYmxlMi5wbmcnKSkKYGBgCgoKV2Ugd2lsbCBwZXJmb3JtIGFuYWx5c2VzIHNpbWlsYXIgdG8gdGhvc2UgaW4gdGhlc2UgYXJ0aWNsZXMsIGhvd2V2ZXIgKip3ZSB3aWxsIG5vdCB0cnkgdG8gcmVjcmVhdGUgdGhlbSoqLCBpbnN0ZWFkIHdlIHdpbGwgc2ltcGxpZnkgb3VyIGFuYWx5c2lzIHRvIGFsbG93IHVzIHRvIGZvY3VzIG9uIG11bHRpY29saW5lYXJpdHkuCgoKVGhlcmVmb3JlIHdlIHdpbGwgdXNlIGEgc3Vic2V0IG9mIHRoZSBsaXN0ZWQgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFuZCB0aGV5IHdpbGwgYmUgY29uc2lzdGVudCBmb3IgYm90aCBhbmFseXNlcyB0aGF0IHdlIHdpbGwgcGVyZm9ybSwgd2l0aCB0aGUgZXhjZXB0aW9uIHRoYXQgb25lIGFuYWx5c2lzIHdpbGwgaGF2ZSA2IGRlbW9ncmFwaGljIHZhcmlhYmxlcyBsaWtlIHRoZSBhbmFseXNpcyBpbiB0aGUgW0Rvbm9odWUsIGV0IGFsLl0oaHR0cHM6Ly93d3cubmJlci5vcmcvcGFwZXJzL3cyMzUxMC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gYXJ0aWNsZSBhbmQgdGhlIG90aGVyIHdpbGwgaGF2ZSAzNiBkZW1vZ3JwYWhpYyB2YXJpYWJsZXMgbGlrZSB0aGUgYW5hbHlzaXMgaW4gdGhlIFtMb3R0IGFuZCBNdXN0YXJkXShodHRwczovL2NoaWNhZ291bmJvdW5kLnVjaGljYWdvLmVkdS9jZ2kvdmlld2NvbnRlbnQuY2dpP2FydGljbGU9MTE1MCZjb250ZXh0PWxhd19hbmRfZWNvbm9taWNzKXt0YXJnZXQ9Il9ibGFuayJ9IGFydGljbGUuCgoKIyAqKk1haW4gUXVlc3Rpb24qKgoqKiogCgojIyMjIHsubWFpbl9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IE91ciBtYWluIHF1ZXN0aW9uOiA8L3U+PC9iPgoKMSkgSG93IGRvZXMgdGhlIGluY2x1c2lvbiBvZiBkaWZmZXJlbnQgbnVtYmVycyBvZiBhZ2UgZ3JvdXBzIGluZmx1ZW5jZSB0aGUgcmVzdWx0cyBvZiBhbiBhbmFseXNpcyBvZiByaWdodCB0byBjYXJyeSBsYXdzIGFuZCB2aW9sZW5jZSByYXRlcz8KCiMjIyMKCgojICoqTGVhcm5pbmcgT2JqZWN0aXZlcyoqIAoqKiogCgo8dT4qKlN0YXRpc3RpY2FsIExlYXJuaW5nIE9iamVjdGl2ZXM6Kio8L3U+IAoKSW4gdGhpcyBjYXNlIHN0dWR5LCBzdHVkZW50cyB3aWxsIGxlYXJuOiAgCjEpIHdoYXQgbXVsdGljb2xpbmVhcml0eSBpcyBhbmQgaG93IGl0IGNhbiBpbmZsdWVuY2UgbGluZWFyIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzICAKMikgaG93IHRvIGxvb2sgZm9yIHRoZSBwcmVzZW5jZSBvZiBtdWx0aWNvbGluYXJpdHkgIAozKSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG11bHRpY29saW5lYXJpdHkgYW5kIGNvcnJlbGF0aW9uICAKCjx1PioqRGF0YSBzY2llbmNlIExlYXJuaW5nIE9iamVjdGl2ZXM6Kio8L3U+CgoxKSBqb2luaW5nIGRhdGEgZnJvbSBtdWx0aXBsZSBzb3VyY2VzIChkcGx5cikgIAoyKSByZXNoYXBpbmcgZGF0YSBpbnRvIGRpZmZlcmVudCBmb3JtYXRzICh0aWR5cikgIAoyKSB2aXN1YWxpemF0aW9ucyAoZ2dwbG90MikgIAoKCldlIHdpbGwgZXNwZWNpYWxseSBmb2N1cyBvbiB1c2luZyBwYWNrYWdlcyBhbmQgZnVuY3Rpb25zIGZyb20gdGhlIFtgVGlkeXZlcnNlYF0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0sIHN1Y2ggYXMgYGRwbHlyYCBhbmQgYGdncGxvdDJgLiBUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGVmZmljaWVudC4KCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKIyAqKkNvbnRleHQqKgoqKioKClNvIHdoYXQgZXhhY3RseSBpcyBhICoqcmlnaHQtdG8tY2FycnkgbGF3Kio/CgpJdCBpcyBhIGxhdyB0aGF0c3BlY2lmaWVzIGlmIGFuZCBob3cgY2l0aXplbnMgYXJlIGFsbG93ZWQgdG8gaGF2ZSBhIGZpcmVhcm0gb24gdGhlaXIgcGVyc29uIG9yIG5lYXJieSAoZm9yIGV4YW1wbGUgaW4gdGhlIGNpdGl6ZW4ncyBjYXIpIGluIHB1YmxpYy4gCgpUaGUgW1NlY29uZCBBbWVuZG1lbnRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NlY29uZF9BbWVuZG1lbnRfdG9fdGhlX1VuaXRlZF9TdGF0ZXNfQ29uc3RpdHV0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9IHRvIHRoZSBVbml0ZWQgU3RhdGVzIENvbnN0aXR1dGlvbiBndWFyYW50ZWVzIHRoZSByaWdodCB0byAia2VlcCBhbmQgYmVhciBhcm1zIi4gVGhlIGFtZW5kbWVudCB3YXMgcmF0aWZpZWQgaW4gMTc5MSBhcyBwYXJ0IG9mIHRoZSBbQmlsbCBvZiBSaWdodHNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1VuaXRlZF9TdGF0ZXNfQmlsbF9vZl9SaWdodHMpe3RhcmdldD0iX2JsYW5rIn0uCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LmhlaWdodCA9ICc1MCUnLCBvdXQud2lkdGggPSAnNTAlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy83Lzc5L0JpbGxfb2ZfUmlnaHRzX1BnMW9mMV9BQy5qcGciKQpgYGAKCkhvd2V2ZXIsIHRoZXJlIGFyZSBubyBmZWRlcmFsIGxhd3MgYWJvdXQgY2FycnlpbmcgZmlyZWFybXMgaW4gcHVibGljLiAKClRoZXNlIGxhd3MgYXJlIGNyZWF0ZWQgYW5kIGVuZm9yY2VkIGF0IHRoZSBzdGF0ZSBsZXZlbC4gU2F0ZXMgdmFyeSBncmVhdGx5IGluIHRoZWlyIGxhd3MgYWJvdXQgdGhlIHJpZ2h0IHRvIGNhcnJ5IGZpcmVhcm1zLiBTb21lIHJlcXVpcmUgZXh0ZW5zaXZlIGVmZm9ydCB0byBvYnRhaW4gYSBwZXJtaXQgdG8gbGVnYWxseSBjYXJyeSBhIGZpcmVhcm0sIHdoaWxlIG90aGVyIHN0YXRlcyByZXF1aXJlIHZlcnkgbWluaW1hbCBlZmZvcnQgdG8gbGVnYWxseSBjYXJyeSBhIGZpcmVhcm0uCgoKQWNjb3JkaW5nIHRvIFdpa2lwZWRpYSBhYm91dCB0aGUgaGlzdG9yeSBvZiByaWdodC10by1jYXJyeSBwb2xpY2llcyBpbiB0aGUgVW5pdGVkIFN0YXRlczoKCj4gUHVibGljIHBlcmNlcHRpb24gb24gY29uY2VhbGVkIGNhcnJ5IHZzIG9wZW4gY2FycnkgaGFzIGxhcmdlbHkgZmxpcHBlZC4gSW4gdGhlIGVhcmx5IGRheXMgb2YgdGhlIFVuaXRlZCBTdGF0ZXMsIG9wZW4gY2Fycnlpbmcgb2YgZmlyZWFybXMsIGxvbmcgZ3VucyBhbmQgcmV2b2x2ZXJzIHdhcyBhIGNvbW1vbiBhbmQgd2VsbC1hY2NlcHRlZCBwcmFjdGljZS4gU2VlaW5nIGd1bnMgY2FycmllZCBvcGVubHkgd2FzIG5vdCBjb25zaWRlcmVkIHRvIGJlIGFueSBjYXVzZSBmb3IgYWxhcm0uIFRoZXJlZm9yZSwgYW55b25lIHdobyB3b3VsZCBjYXJyeSBhIGZpcmVhcm0gYnV0IGF0dGVtcHQgdG8gY29uY2VhbCBpdCB3YXMgY29uc2lkZXJlZCB0byBoYXZlIHNvbWV0aGluZyB0byBoaWRlLCBhbmQgcHJlc3VtZWQgdG8gYmUgYSBjcmltaW5hbC4gRm9yIHRoaXMgcmVhc29uLCBjb25jZWFsZWQgY2Fycnkgd2FzIGRlbm91bmNlZCBhcyBhIGRldGVzdGFibGUgcHJhY3RpY2UgaW4gdGhlIGVhcmx5IGRheXMgb2YgdGhlIFVuaXRlZCBTdGF0ZXMuCgo+IENvbmNlYWxlZCB3ZWFwb25zIGJhbnMgd2VyZSBwYXNzZWQgaW4gS2VudHVja3kgYW5kIExvdWlzaWFuYSBpbiAxODEzLiAoSW4gdGhvc2UgZGF5cyBvcGVuIGNhcnJ5IG9mIHdlYXBvbnMgZm9yIHNlbGYtZGVmZW5zZSB3YXMgY29uc2lkZXJlZCBhY2NlcHRhYmxlOyBjb25jZWFsZWQgY2Fycnkgd2FzIGRlbm91bmNlZCBhcyB0aGUgcHJhY3RpY2Ugb2YgY3JpbWluYWxzLikgQnkgMTg1OSwgSW5kaWFuYSwgVGVubmVzc2VlLCBWaXJnaW5pYSwgQWxhYmFtYSwgYW5kIE9oaW8gaGFkIGZvbGxvd2VkIHN1aXQuIEJ5IHRoZSBlbmQgb2YgdGhlIG5pbmV0ZWVudGggY2VudHVyeSwgc2ltaWxhciBsYXdzIHdlcmUgcGFzc2VkIGluIHBsYWNlcyBzdWNoIGFzIFRleGFzLCBGbG9yaWRhLCBhbmQgT2tsYWhvbWEsIHdoaWNoIHByb3RlY3RlZCBzb21lIGd1biByaWdodHMgaW4gdGhlaXIgc3RhdGUgY29uc3RpdHV0aW9ucy4gQmVmb3JlIHRoZSBtaWQgMTkwMHMsIG1vc3QgVS5TLiBzdGF0ZXMgaGFkIHBhc3NlZCBjb25jZWFsZWQgY2FycnkgbGF3cyByYXRoZXIgdGhhbiBiYW5uaW5nIHdlYXBvbnMgY29tcGxldGVseS4gVW50aWwgdGhlIGxhdGUgMTk5MHMsIG1hbnkgU291dGhlcm4gc3RhdGVzIHdlcmUgZWl0aGVyICJOby1Jc3N1ZSIgb3IgIlJlc3RyaWN0aXZlIE1heS1Jc3N1ZSIuIFNpbmNlIHRoZW4sIHRoZXNlIHN0YXRlcyBoYXZlIGxhcmdlbHkgZW5hY3RlZCAiU2hhbGwtSXNzdWUiIGxpY2Vuc2luZyBsYXdzLCB3aXRoIG51bWVyb3VzIHN0YXRlcyBsZWdhbGl6aW5nICJVbnJlc3RyaWN0ZWQgY29uY2VhbGVkIGNhcnJ5Ii4KClNlZSBbaGVyZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSGlzdG9yeV9vZl9jb25jZWFsZWRfY2FycnlfaW5fdGhlX1UuUy4pe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24uCgpIZXJlIGFyZSB0aGUgZ2VuZXJhbCBjYXRlZ29yaWVzIG9mIFJpZ2h0IHRvIENhcnJ5IExhd3M6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LmhlaWdodCA9ICcxMDAlJywgb3V0LndpZHRoID0gJzEwMCUnLCBmaWcuYWxpZ249J2NlbnRlcid9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoImltZyIsICJSVEMucG5nIikpCmBgYApbc291cmNlXShodHRwczovL3d3dy5ucmFpbGEub3JnL2d1bi1sYXdzLyl7dGFyZ2V0PSJfYmxhbmsifQoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQuaGVpZ2h0ID0gJzEwMCUnLCBvdXQud2lkdGggPSAnMTAwJScsIGZpZy5hbGlnbj0nY2VudGVyJ30Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZSgiaW1nIiwgIlJUQ19tYXAucG5nIikpCmBgYAoKW3NvdXJjZV0oaHR0cHM6Ly93d3cubnJhaWxhLm9yZy9ndW4tbGF3cy8pe3RhcmdldD0iX2JsYW5rIn0KCllvdSBjYW4gc2VlIHRoYXQgbm9uZSBvZiB0aGUgZmlmdHkgc3RhdGVzIGhhdmUgbm8taXNzdWUgbGF3cyBjdXJyZW50bHksIG1lYW5pbmcgdGhhdCBhbGwgc3RhdGVzIGFsbG93IHRoZSByaWdodCB0byBjYXJyeSBmaXJlYXJtcyBhdCBsZWFzdCBpbiBzb21lIHdheSwgaG93ZXZlciB0aGUgbGV2ZWwgb2YgcmVzdHJpY3Rpb25zIGlzIGRyYW1hdGljYWxseSBkaWZmZXJlbnQgZnJvbSBvbmUgc3RhdGUgdG8gYW5vdGhlci4KCkhlcmUgeW91IGNhbiBzZWUgaG93IHRoZXNlIGxhd3MgaGF2ZSBjaGFuZ2VkIG92ZXIgdGltZSBhcm91bmQgdGhlIGNvdW50cnk6CmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQuaGVpZ2h0ID0gJzEwMCUnLCBvdXQud2lkdGggPSAnMTAwJScsIGZpZy5hbGlnbj0nY2VudGVyJ30Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdXBsb2FkLndpa2ltZWRpYS5vcmcvd2lraXBlZGlhL2NvbW1vbnMvdGh1bWIvNS81YS9SaWdodF90b19DYXJyeSUyQ190aW1lbGluZS5naWYvNjIwcHgtUmlnaHRfdG9fQ2FycnklMkNfdGltZWxpbmUuZ2lmIikKYGBgCgpUaGVyZSBpcyB2YXJpYXRpb24gZnJvbSBzdGF0ZSB0byBzdGF0ZSBldmVuIHdpdGhpbiB0aGUgc2FtZSBnZW5lcmFsIGNhdGVnb3J5OgoKRm9yIGV4YW1wbGUgaGVyZSBhcmUgdGhlIFtjdXJyZW50IGNhcnJ5IGxhd3MgaW4gSWRhaG9dKGh0dHBzOi8vd3d3Lm5yYWlsYS5vcmcvZ3VuLWxhd3Mvc3RhdGUtZ3VuLWxhd3MvaWRhaG8vKSB3aGljaCBpcyBjb25zaWRlcmVkIGFuICJVbnJlc3RyaWN0ZWQgLSBubyBwZXJtaXQgcmVxdWlyZWQiIHN0YXRlOgoKPklkYWhvIHBlcm1pdHMgdGhlIG9wZW4gY2Fycnlpbmcgb2YgZmlyZWFybXMuCgo+SWRhaG8gbGF3IHBlcm1pdHMgYm90aCByZXNpZGVudHMgYW5kIG5vbi1yZXNpZGVudHMgd2hvIGFyZSBhdCBsZWFzdCAxOCB5ZWFycyBvbGQgdG8gY2FycnkgY29uY2VhbGVkIHdlYXBvbnMsIHdpdGhvdXQgYSBjYXJyeSBsaWNlbnNlLCBvdXRzaWRlIHRoZSBsaW1pdHMgb2Ygb3IgY29uZmluZXMgb2YgYW55IGNpdHksIHByb3ZpZGVkIHRoZSBwZXJzb24gaXMgbm90IG90aGVyd2lzZSBkaXNxdWFsaWZpZWQgZnJvbSBiZWluZyBpc3N1ZWQgYSBsaWNlbnNlIHRvIGNhcnJ5LgoKPkEgcGVyc29uIG1heSBhbHNvIGNhcnJ5IGNvbmNlYWxlZCB3ZWFwb25zIG9uIG9yIGFib3V0IGhpcyBvciBoZXIgcGVyc29uLCB3aXRob3V0IGEgbGljZW5zZSwgaW4gdGhlIHBlcnNvbuKAmXMgb3duIHBsYWNlIG9mIGFib2RlIG9yIGZpeGVkIHBsYWNlIG9mIGJ1c2luZXNzLCBvbiBwcm9wZXJ0eSBpbiB3aGljaCB0aGUgcGVyc29uIGhhcyBhbnkgb3duZXJzaGlwIG9yIGxlYXNlaG9sZCBpbnRlcmVzdCwgb3Igb24gcHJpdmF0ZSBwcm9wZXJ0eSB3aGVyZSB0aGUgcGVyc29uIGhhcyBwZXJtaXNzaW9uIHRvIGNhcnJ5IGZyb20gYW55IHBlcnNvbiB3aG8gaGFzIGFuIG93bmVyc2hpcCBvciBsZWFzZWhvbGQgaW50ZXJlc3QgaW4gdGhhdCBwcm9wZXJ0eS4gCgo+U3RhdGUgbGF3IGFsc28gYWxsb3dzIGFueSByZXNpZGVudCBvZiBJZGFobyBvciBhIGN1cnJlbnQgbWVtYmVyIG9mIHRoZSBhcm1lZCBmb3JjZXMgb2YgdGhlIFVuaXRlZCBTdGF0ZXMgdG8gY2FycnkgYSBjb25jZWFsZWQgaGFuZGd1biB3aXRob3V0IGEgbGljZW5zZSB0byBjYXJyeSwgcHJvdmlkZWQgdGhlIHBlcnNvbiBpcyBvdmVyIDE4IHllYXJzIG9sZCBhbmQgbm90IGRpc3F1YWxpZmllZCBmcm9tIGJlaW5nIGlzc3VlZCBhIGxpY2Vuc2UgdG8gY2FycnkgY29uY2VhbGVkIHdlYXBvbnMgdW5kZXIgc3RhdGUgbGF3LiBBbiBhbWVuZG1lbnQgdG8gc3RhdGUgbGF3IHRoYXQgdGFrZXMgZWZmZWN0IG9uIEp1bHkgMSwgMjAyMCBjaGFuZ2VzIHRoZSByZWZlcmVuY2UgaW4gdGhlIGFib3ZlIGxhdyBmcm9tIOKAnGEgcmVzaWRlbnQgb2YgSWRhaG/igJ0gdG8g4oCcYW55IGNpdGl6ZW4gb2YgdGhlIFVuaXRlZCBTdGF0ZXMu4oCdICAKCgpBbmQgaGVyZSBhcmUgdGhlIFtjdXJyZW50IGNhcnJ5IGxhd3MgaW4gQXJpem9uYV0oaHR0cHM6Ly93d3cubnJhaWxhLm9yZy9ndW4tbGF3cy9zdGF0ZS1ndW4tbGF3cy9hcml6b25hLykgd2hpY2ggaXMgYWxzbyBjb25zaWRlcmVkIGFuICJVbnJlc3RyaWN0ZWQtIC0gbm8gcGVybWl0IHJlcXVpcmVkIiBzdGF0ZToKCj4gQXJpem9uYSByZXNwZWN0cyB0aGUgcmlnaHQgb2YgbGF3IGFiaWRpbmcgY2l0aXplbnMgdG8gb3Blbmx5IGNhcnJ5IGEgaGFuZGd1bi4KCj4gQW55IHBlcnNvbiAyMSB5ZWFycyBvZiBhZ2Ugb3Igb2xkZXIsIHdobyBpcyBub3QgcHJvaGliaXRlZCBwb3NzZXNzb3IsIG1heSBjYXJyeSBhIHdlYXBvbiBvcGVubHkgb3IgY29uY2VhbGVkIHdpdGhvdXQgdGhlIG5lZWQgZm9yIGEgbGljZW5zZS4gQW55IHBlcnNvbiBjYXJyeWluZyB3aXRob3V0IGEgbGljZW5zZSBtdXN0IGFja25vd2xlZGdlIGFuZCBjb21wbHkgd2l0aCB0aGUgZGVtYW5kcyBvZiBhIGxhdyBlbmZvcmNlbWVudCBvZmZpY2VyIHdoZW4gYXNrZWQgaWYgaGUvc2hlIGlzIGNhcnJ5aW5nIGEgY29uY2VhbGVkIGRlYWRseSB3ZWFwb24sIGlmIHRoZSBvZmZpY2VyIGhhcyBpbml0aWF0ZWQgYW4gImludmVzdGlnYXRpb24iIHN1Y2ggYXMgYSB0cmFmZmljIHN0b3AuCgpOb3RpY2UgdGhhdCBjaXRpemVucyBpbiBJZGFobyBvbmx5IG5lZWQgdG8gYmUgMTggdG8gY2FycnkgYSBmaXJlYXJtLCB3aGVyZWFzIHRoZXkgbXVzdCBiZSAyMSBpbiBBcml6b25hLiAKCgpJbiBjb250cmFzdCBoZXJlIGlzIGFuIGV4YW1wbGUgb2YgW2N1cnJlbnQgY2FycnkgbGF3cyBpbiBNYXJ5bGFuZF0oaHR0cHM6Ly93d3cubnJhaWxhLm9yZy9ndW4tbGF3cy9zdGF0ZS1ndW4tbGF3cy9tYXJ5bGFuZC8pIHdoaWNoIGlzIGNvbnNpZGVyZWQgYSAiUmlnaHRzIFJlc3RyaWN0ZWQtVmVyeSBMaW1pdGVkIElzc3VlIiBzdGF0ZToKCj5DYXJyeWluZyBhbmQgVHJhbnNwb3J0YXRpb24gaW4gVmVoaWNsZXMKSXQgaXMgdW5sYXdmdWwgZm9yIGFueSBwZXJzb24gd2l0aG91dCBhIHBlcm1pdCB0byB3ZWFyIG9yIGNhcnJ5IGEgaGFuZGd1biwgb3Blbmx5IG9yIGNvbmNlYWxlZCwgdXBvbiBvciBhYm91dCBoaXMgcGVyc29uLiAgSXQgaXMgYWxzbyB1bmxhd2Z1bCBmb3IgYW55IHBlcnNvbiB0byBrbm93aW5nbHkgdHJhbnNwb3J0IGEgaGFuZGd1biBpbiBhbnkgdmVoaWNsZSB0cmF2ZWxpbmcgb24gcHVibGljIHJvYWRzLCBoaWdod2F5cywgd2F0ZXJ3YXlzIG9yIGFpcndheXMsIG9yIHVwb24gcm9hZHMgb3IgcGFya2luZyBsb3RzIGdlbmVyYWxseSB1c2VkIGJ5IHRoZSBwdWJsaWMuIFRoaXMgZG9lcyBub3QgYXBwbHkgdG8gYW55IHBlcnNvbiB3ZWFyaW5nLCBjYXJyeWluZyBvciB0cmFuc3BvcnRpbmcgYSBoYW5kZ3VuIHdpdGhpbiB0aGUgY29uZmluZXMgb2YgcmVhbCBlc3RhdGUgb3duZWQgb3IgbGVhc2VkIGJ5IGhpbSwgb3Igb24gd2hpY2ggaGUgcmVzaWRlcywgb3Igd2l0aGluIHRoZSBjb25maW5lcyBvZiBhIGJ1c2luZXNzIGVzdGFibGlzaG1lbnQgb3duZWQgb3IgbGVhc2VkIGJ5IGhpbS4KCj5QZXJtaXQgVG8gQ2FycnkKQXBwbGljYXRpb24gZm9yIGEgcGVybWl0IHRvIGNhcnJ5IGEgaGFuZGd1biBpcyBtYWRlIHRvIHRoZSBTZWNyZXRhcnkgb2YgU3RhdGUgUG9saWNlLiAgSW4gYWRkaXRpb24gdG8gdGhlIHByaW50ZWQgYXBwbGljYXRpb24gZm9ybSwgdGhlIGFwcGxpY2FudCBzaG91bGQgc3VibWl0IGEgbm90YXJpemVkIGxldHRlciBzdGF0aW5nIHRoZSByZWFzb25zIHdoeSBoZSBpcyBhcHBseWluZyBmb3IgYSBwZXJtaXQuCgoKYXZvY2Fkby4uLi5SaWdodCB0byBjYXJyeSBhbmQgY292aWQgbWFza3M/CgojICoqTGltaXRhdGlvbnMqKgoqKiogClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBjb25zaWRlcmF0aW9ucyByZWdhcmRpbmcgdGhpcyBkYXRhIGFuYWx5c2lzIHRvIGtlZXAgaW4gbWluZDogCgoxKSBXZSBkbyBub3QgdXNlIGFsbCBvZiB0aGUgZGF0YSB1c2VkIGJ5IGVpdGhlciB0aGUgIFtMb3R0IGFuZCBNdXN0YXJkXShodHRwczovL2NoaWNhZ291bmJvdW5kLnVjaGljYWdvLmVkdS9jZ2kvdmlld2NvbnRlbnQuY2dpP2FydGljbGU9MTE1MCZjb250ZXh0PWxhd19hbmRfZWNvbm9taWNzKXt0YXJnZXQ9Il9ibGFuayJ9IG9yIFtEb25vaHVlLCBldCBhbC5dKGh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGFuYWx5c2VzLCBub3IgZG8gd2UgcGVyZm9ybSB0aGUgc2FtZSBhbmFseXNpcyBvZiBlYWNoIGFydGljbGUuIFdlIGluc3RlYWQgcGVyZm9ybSBhIG11Y2ggc2ltcGxlciBhbmFseXNpcyB3aXRoIGxlc3MgdmFyaWFibGVzIGZvciB0aGUgcHVycG9zZXMgb2YgaWxsdXN0cmF0aW9uIG9mIHRoZSBjb25jZXB0IG9mIG11bHRpY29sbGluZWFyaXR5IGFuZCBpdHMgaW5mbHVlbmNlIG9uIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLCBub3QgdG8gcmVwcm9kdWNlIGVpdGhlciBhbmFseXNpcy4KCjIpIEJlY2F1c2Ugb3VyIGFuYWx5c2lzIGlzIGFuIG92ZXJzaW1wbGlmaWNhdGlvbiwgb3VyIGFuYWx5c2lzIHNob3VsZCBub3QgYmUgdXNlZCBmb3IgZGV0ZXJtaW5pbmcgcG9saWN5IGNoYW5nZXMsIGluc3RlYWQgd2Ugc3VnZ2VzdCB0aGF0IHVzZXJzIGNvbnN1bHQgd2l0aCBhIHNwZWNpYWxpc3QuCgoKV2Ugd291bGQgYWxzbyBsaWtlIHRvIG5vdGUgdGhhdC4uLkFWT0NBRE8KSXQgaXMgaW1wb3J0YW50IHRoYXQgd2UgZG8gbm90IHRyZWF0IHJhY2UgYXMgYW4gb2JqZWN0aXZlIG1lYXN1cmUuIERlc3BpdGUgdGhpcywgaXQgY2FuIGJlIHVzZWQgdG8gYWR2YW5jZSBzY2llbnRpZmljIGlucXVpcnkuIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHRoaXMgdG9waWMsIHdlIGhhdmUgaW5jbHVkZWQgYSBsaW5rIHRvIGEgW3BhcGVyIG9uIHRoZSB1c2Ugb2YgcmFjZSBhcyBhIG1lYXN1cmUgaW4gZXBpZGVtaW9sb2d5XShodHRwczovL2FjYWRlbWljLm91cC5jb20vZXBpcmV2L2FydGljbGUvMjIvMi8xODcvNDU2OTQyKS4gCgoKV2Ugd2lsbCBiZWdpbiBieSBsb2FkaW5nIHRoZSBwYWNrYWdlcyB0aGF0IHdlIHdpbGwgbmVlZDoKCmBgYHtyfQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHBkZnRvb2xzKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZm9yY2F0cykKCmxpYnJhcnkoY2FyKSAjIHZpZiBmdW5jdGlvbgpsaWJyYXJ5KHBsbSkgIyBmaXhlZCBlZmZlY3QgbW9kZWwsIGxpbmVhciByZWdyZXNzaW9uCmxpYnJhcnkoYnJvb20pICMgdGlkeSBvdXRwdXQKbGlicmFyeSh0aWR5dmVyc2UpICMgZ2VuZXJhbCB3cmFuZ2xpbmcgZnVuY3Rpb25zCmxpYnJhcnkoY293cGxvdCkgIyB0byBwcm9kdWNlIHBsb3Qgb2YgcGxvdHMgCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGxhdGV4MmV4cCkKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KGdnY29ycnBsb3QpCmxpYnJhcnkocnNhbXBsZSkKCnNldC5zZWVkKDk5OSkKYGBgCgoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCB0aGUgQ1NWIGZpbGUgZGF0YQpbY2FyXSAgfCB0byBjYWxjdWxhdGUgdmlmIHZhbHVlcwpbcHVycnJdIHwgdG8gY29tYmluZSBtdWx0aXBsZSB0aWJibGVzIHdpdGhpbiBhIGxpc3Qgb2YgdGliYmxlcwpbZm9yY2F0c10gfCB0byBjb2xsYXBzZSBsZXZlbHMgb2YgZmFjdG9ycyBpbnRvIG1vcmUgc3VtbWFyaXNlZCB2ZXJzaW9ucwpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCgojICoqV2hhdCBhcmUgdGhlIGRhdGE/KioKKioqCgpCZWxvdyBpcyBhIHRhYmxlIGZyb20gdGhlIFtEb25vaHVlLCBldCBhbC5dKGh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHBhcGVyIHRoYXQgc2hvd3MgdGhlIGRhdGEgdXNlZCBpbiBib3RoIGFuYWx5c2VzLCB3aGVyZSBEQVcgc3RhbmRzIGZvciBbRG9ub2h1ZSwgZXQgYWwuXShodHRwczovL3d3dy5uYmVyLm9yZy9wYXBlcnMvdzIzNTEwLnBkZil7dGFyZ2V0PSJfYmxhbmsifSBhbmQgTE0gc3RhbmRzIGZvciBbTG90dCBhbmQgTXVzdGFyZF0oaHR0cHM6Ly9jaGljYWdvdW5ib3VuZC51Y2hpY2Fnby5lZHUvY2dpL3ZpZXdjb250ZW50LmNnaT9hcnRpY2xlPTExNTAmY29udGV4dD1sYXdfYW5kX2Vjb25vbWljcyl7dGFyZ2V0PSJfYmxhbmsifS4KCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LmhlaWdodCA9ICcxMDAlJywgb3V0LndpZHRoID0gJzEwMCUnLCBmaWcuYWxpZ249J2NlbnRlcid9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoImltZyIsICJEb25vaHVlX0FwcGVuZGl4Si5wbmciKSkKYGBgCgpXZSB3aWxsIGJlIHVzaW5nIGEgc3Vic2V0IG9mIHRoZXNlIHZhcmlhYmxlcywgd2hpY2ggYXJlIGhpZ2hsaWdodGVkIGluIGdyZWVuOgoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQuaGVpZ2h0ID0gJzEwMCUnLCBvdXQud2lkdGggPSAnMTAwJScsIGZpZy5hbGlnbj0nY2VudGVyJ30Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZSgiaW1nIiwgIm91cmRhdGEucG5nIikpCmBgYAoKCiMgKipEYXRhIEltcG9ydCoqCioqKgoKCgojIyBEZW1vZ3JhcGhpYyBhbmQgb3B1bGF0aW9uIGRhdGEKClRvIG9idGFpbiBpbmZvcm1hdGlvbiBhYm91dCBhZ2UsIHNleCwgYW5kIHJhY2UsIGFuZCBvdmVyYWxsIHBvcHVsYXRpb24gd2Ugd2lsbCB1c2UgVVMgQ2Vuc3VzIEJ1cmVhdSBkYXRhLCBqdXN0IGxpa2UgYm90aCBvZiB0aGUgYXJ0aWNsZXMuIFRoZSBjZXNudXMgZGF0YSBpcyBhdmFpbGFibGUgZm9yIGRpZmZlcmVudCB0aW1lIHNwYW5zLiBIZXJlIGFyZSB0aGUgbGlua3MgZm9yIHRoZSB5ZWFycyB1c2VkIGluIG91ciBhbmFseXNpcy4gV2Ugd2lsbCB1c2UgZGF0YSBmcm9tIDE5NzcgdG8gMjAxMC4KCkRhdGEgICB8IExpbmsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQoqKnllYXJzIDE5NzcgdG8gMTk3OSoqICB8IFtsaW5rXShodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9wcm9ncmFtcy1zdXJ2ZXlzL3BvcGVzdC90YWJsZXMvMTkwMC0xOTgwL3N0YXRlL2FzcmgvKSAgCioqeWVhcnMgMTk4MCB0byAxOTg5KiogIHwgW2xpbmtdKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvcG9wZXN0L3RhYmxlcy8xOTgwLTE5OTAvY291bnRpZXMvYXNyaC8pICogY291bnR5IGRhdGEgd2FzIHVzZWQgZm9yIHRoaXMgZGVjYWRlIHdoaWNoIGFsc28gaGFzIHN0YXRlIGluZm9ybWF0aW9uCioqeWVhcnMgMTk5MCB0byAxOTk5KiogIHwgW2xpbmtdKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvcG9wZXN0L3RhYmxlcy8xOTkwLTIwMDAvc3RhdGUvYXNyaC8pCioqeWVhcnMgMjAwMCB0byAyMDEwKiogIHwgW2xpbmtdKGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvZGF0YS9kYXRhc2V0cy90aW1lLXNlcmllcy9kZW1vL3BvcGVzdC9pbnRlcmNlbnNhbC0yMDAwLTIwMTAtc3RhdGUuaHRtbCkgPGJyPiBbdGVjaG5pY2FsIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvcG9wZXN0L3RlY2huaWNhbC1kb2N1bWVudGF0aW9uL2ZpbGUtbGF5b3V0cy8yMDAwLTIwMTAvaW50ZXJjZW5zYWwvc3RhdGUvc3QtZXN0MDBpbnQtYWxsZGF0YS5wZGYpe3RhcmdldD0iX2JsYW5rIn0KClRvIGltcG9ydCB0aGUgZGF0YSB3ZSB3aWxsIHVzZSB0aGUgYHJlYWRfY3N2KClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVhZHJgIHBhY2thZ2UgZm9yIHRoZSBjc3YgZmlsZXMuIEluIHNvbWUgZGVjYWRlcywgdGhlcmUgYXJlIHNlcGFyYXRlIGZpbGVzIGZvciBlYWNoIHllYXIsIHdlIHdpbGwgcmVhZCBlYWNoIG9mIHRoZXNlIHRvZ2V0aGVyIHVzaW5nIHRoZSBiYXNlIGBsaXN0LmZpbGVzKClgIGZ1bmN0aW9uIHRvIGdldCBhbGwgb2YgdGhlIG5hbWVzIGZvciBlYWNoIGZpbGUgYW5kIHRoZW4gdGhlIGBtYXAoKWAgZnVuY3Rpb24gb2YgdGhlIGBwdXJycmAgcGFja2FnZSB0byBhcHBseSB0aGUgYHJlYWRfY3N2KClgIGZ1bmN0aW9uIG9uIGFsbCBvZiB0aGUgZmlsZSBwYXRocyBpbiB0aGUgbGlzdCBjcmVhdGVkIGJ5IGBsaXN0LmZpbGVzKClgLiBGb3IgeWVhcnMgdGhhdCBhcmUgdHh0IGZpbGVzIHdlIHdpbGwgdXNlIGByZWFkX3RhYmxlMigpYCBhbHNvIGZvIHRoZSBgcmVhZHJgIHBhY2thZ2UuIFRoZSBgcmVhZF90YWJsZTIoKWAgZnVuY3Rpb24sIHVubGlrZSB0aGUgYHJlYWRfdGFibGUoKWAsICBhbGxvd3MgZm9yIGFueSBudW1iZXIgb2Ygd2hpdGVzcGFjZSBjaGFyYWN0ZXJzIGJldHdlZW4gY29sdW1ucywgYW5kIHRoZSBsaW5lcyBjYW4gYmUgb2YgZGlmZmVyZW50IGxlbmd0aHMuCgpBVk9DQURPIEkgYW0gYSBiaXQgY29uZnVzZWQgYWJvdXQgdGhlIGxhc3QgZGVjYWRlLi4uIGl0J3Mgb25seSBvbmUgZmlsZSBidXQgaXQgc2VlbXMgdG8gbmVlZCBtYXAuLi4KCmBgYHtyfQoKZGVtXzc3Xzc5IDwtIHJlYWRfY3N2KCJkb2NzL0RlbW9ncmFwaGljcy9EZWNhZGVfMTk3MC9wZS0xOS5jc3YiLCBza2lwID0gNSkKCmRlbV84MF84OSA8LSBsaXN0LmZpbGVzKHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHBhdGggPSAiZG9jcy9EZW1vZ3JhcGhpY3MvRGVjYWRlXzE5ODAvIiwKICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIqLmNzdiIsCiAgICAgICAgICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKSAlPiUgCiAgbWFwKH5yZWFkX2NzdiguLCBza2lwPTUpKQoKZGVtXzkwXzk5IDwtIGxpc3QuZmlsZXMocmVjdXJzaXZlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgcGF0aCA9ICJkb2NzL0RlbW9ncmFwaGljcy9EZWNhZGVfMTk5MC8iLAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIioudHh0IiwKICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lcyA9IFRSVUUpICU+JSAKICBtYXAofnJlYWRfdGFibGUyKC4sIHNraXAgPSAxNCkpCgoKZGVtXzAwXzEwXzIgPC0gcmVhZF9jc3YoImRvY3MvRGVtb2dyYXBoaWNzL0RlY2FkZV8yMDAwL3N0LWVzdDAwaW50LWFsbGRhdGEuY3N2IikKCmRlbV8wMF8xMCA8LSBsaXN0LmZpbGVzKHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHBhdGggPSAiZG9jcy9EZW1vZ3JhcGhpY3MvRGVjYWRlXzIwMDAvIiwKICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIqLmNzdiIsCiAgICAgICAgICAgICAgICAgICBmdWxsLm5hbWVzID0gVFJVRSkgJT4lIAogICBtYXAofnJlYWRfY3N2KC4pKQoKaGVhZChkZW1fMDBfMTApCgpgYGAKCk5vdGljZSB0aGF0IHRoZSBgU1RBVEVgIHZhcmlhYmxlIGZvciB0aGUgZGVtb2dyYXBoaWMgZGF0YSBpcyBudW1lcmljLiBUaGF0IGlzIGJlY2F1c2UgaXQgaXMgZW5jb2RlZCBieSBbRmVkZXJhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nIFN0YW5kYXJkIChGSVBTKSBzdGF0ZSBjb2Rlc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmVkZXJhbF9JbmZvcm1hdGlvbl9Qcm9jZXNzaW5nX1N0YW5kYXJkX3N0YXRlX2NvZGUpe3RhcmdldD0iX2JsYW5rIi4gVGh1cyB3ZSBhbHNvIG5lZWQgdG8gaW1wb3J0IGRhdGEgIGFib3V0IEZJUFMgZW5jb2Rpbmcgc28gdGhhdCB3ZSBjYW4gaWRlbnRpZnkgd2hhdCBkYXRhIGNvcnJlc3BvbmRzIHRvIHdoYXQgc3RhdGUuCgoKIyMgU3RhdGUgRklQUyBjb2RlcwoKVGhlIGZvbGxvd2luZyBkYXRhIHdhcyBkb3dubG9hZGVkIGZyb20gdGhlIFtVUyBDZW5zdXMgQnVyZWF1XShodHRwczovL3d3dy5jZW5zdXMuZ292L2dlb2dyYXBoaWVzL3JlZmVyZW5jZS1maWxlcy8yMDE0L2RlbW8vcG9wZXN0LzIwMTQtZ2VvY29kZXMtc3RhdGUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4KClRvIGltcG9ydCB0aGUgZGF0YSB3ZSB3aWxsIHVzZSB0aGUgYHJlYWRfeGxzKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVhZHhsYCBwYWNrYWdlLiBTaW5jZSB0aGUgZmlyc3QgZml2ZSBsaW5lcyBvZiB0aGlzIGV4Y2VsIGlzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzb3VyY2Ugb2YgdGhlIGRhdGEgYW5kIHdoZW4gaXQgd2FzIHJlbGVhc2VkLCB3ZSBuZWVkIHRvIHNraXAgaW1wb3J0aW5nIHRoZXNlIGxpbmVzIHVzaW5nIHRoZSBgc2tpcGAgYXJndW1lbnQgc28gdGhhdCB0aGUgZGF0YSBoYXMgdGhlIHNhbWUgbnVtYmVyIG9mIGNvbHVtbnMgZm9yIGVhY2ggcm93LiAKCmBgYHtyLCBvdXQud2lkdGggPSAiNTAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZSgiaW1nIiwgIkZJUFMucG5nIikpCgpgYGAKCmBgYHtyfQpTVEFURV9GSVBTIDwtIHJlYWRfeGxzKCJkb2NzL1N0YXRlX0ZJUFNfY29kZXMvc3RhdGUtZ2VvY29kZXMtdjIwMTQueGxzIiwgc2tpcCA9IDUpCihTVEFURV9GSVBTKQpgYGAKCiMjIFBvbGljZSBzdGFmZmluZyBkYXRhClRoZSBmb2xsb3dpbmcgZGF0YSB3YXMgZG93bmxvYWRlZCBmcm9tIHRoZSBbRmVkZXJhbCBCdXJlYXUgb2YgSW52ZXN0aWdhdGlvbl0oaHR0cHM6Ly9jcmltZS1kYXRhLWV4cGxvcmVyLmZyLmNsb3VkLmdvdi9kb3dubG9hZHMtYW5kLWRvY3MpLiAKCgpUaGUgYHJlYWRfY3N2KClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVhZHJgIHBhY2thZ2UgZ3Vlc3NlcyB3aGF0IHRoZSBjbGFzcyBpcyBmb3IgZWFjaCB2YXJpYWJsZSwgYnV0IHNvbWV0aW1lcyBpdCBtYWtlcyBtaXN0YWtlcy4gSXQgaXMgZ29vZCB0byBzcGVjaWZ5IHRoZSBjbGFzcyBmb3IgdmFyaWFibGVzIGlmIHlvdSBrbm93IHRoZW0uIFdlIGtub3cgdGhhdCB3ZSB3YW50IHRoZSB2YXJpYWJsZXMgYWJvdXQgbWFsZSBhbmQgZmVtYWxlIGNvdW50cyB0byBiZSBudW1lcmljLiBXZSBjYW4gc3BlY2lmeSB0aGF0IHVzaW5nIHRoZSBgY29sX3R5cGVzID1gIGFyZ3VtZW50LiBTZWUgW2hlcmVdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9yZWFkci5odG1sKSBhbmQgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZWFkci92aWduZXR0ZXMvcmVhZHIuaHRtbCkgZm9yIG1vcmUgaW5mb3JtYXRpb24uCgpgYGB7cn0KcHNfZGF0YSA8LSByZWFkX2NzdigiZG9jcy9Qb2xpY2Vfc3RhZmZpbmcvcGVfMTk2MF8yMDE4LmNzdiIpCnBzX2RhdGEgPC0gcmVhZF9jc3YoImRvY3MvUG9saWNlX3N0YWZmaW5nL3BlXzE5NjBfMjAxOC5jc3YiLAogICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMobWFsZV90b3RhbF9jdCA9ICJuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV90b3RhbF9jdCA9ICJuIikpCgpwc19kYXRhIDwtIHJlYWRfY3N2KCJkb2NzL1BvbGljZV9zdGFmZmluZy9wZV8xOTYwXzIwMTguY3N2IiwKICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9ICBjb2xzKG1hbGVfdG90YWxfY3QgPSBjb2xfZG91YmxlKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlX3RvdGFsX2N0ID0gY29sX2RvdWJsZSgpKSkKaGVhZChwc19kYXRhKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAKYGBgCgoKCiMjIFVuZW1wbHltZW50IGRhdGEKClRoZSBmb2xsb3dpbmcgZGF0YSB3YXMgZG93bmxvYWRlZCBmcm9tIHRoZSBbVS5TLiBCdXJlYXUgb2YgTGFib3IgU3RhdGlzdGljc10oaHR0cHM6Ly9kYXRhLmJscy5nb3YvY2dpLWJpbi9kc3J2P2xhKS4gCgpUaGVyZSBhcmUgZXhjZWwgZmlsZXMgZm9yIGVhY2ggc3RhdGUuICBBcyB5b3UgY2FuIHNlZSwgdGhlcmUgYXJlIG1hbnkgcm93cyB0byBza2lwIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZXJlIGFyZSB0aGUgc2FtZSBudW1iZXIgb2YgY29sdW1ucyBmb3IgZWFjaCByb3cuIFdlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSBzdGF0ZSBuYW1lIGlzIGxvY2F0ZWQgaW4gYSBjb3VwbGUgb2YgdGhlIGZpcnN0IHJvd3MuIAoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoImltZyIsICJVbmVtcC5wbmciKSkKYGBgCgpXZSBjYW4gYWxzbyBzZWUgdGhhdCBoZXJlIGlmIHdlIGp1c3QgdHJ5IHRvIHJlYWQgaW4gdGhlIGZpbGVzIGRpcmVjdGx5LgoKYGBge3J9Cgp1ZV9yYXRlX2RhdGEgPC0gbGlzdC5maWxlcyhyZWN1cnNpdmUgPSBUUlVFLAogICAgICAgICAgICAgICAgICBwYXRoID0gImRvY3MvVW5lbXBsb3ltZW50IiwKICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIqLnhsc3giLAogICAgICAgICAgICAgICAgICBmdWxsLm5hbWVzID0gVFJVRSkgJT4lIAogIG1hcCh+cmVhZF94bHN4KC4pKQogICAgICAKaGVhZCh1ZV9yYXRlX2RhdGEpWzFdCmBgYAoKU28gbm93IHdlIHdpbGwgc2tpcCB0aGUgZmlyc3QgMTAgbGluZXMuIEFuZCBhbHNvIGNyZWF0ZSBhIG5hbWVzIHRpYmJsZSB0aGF0IGNvbnRhaW5zIG9ubHkgdGhlIGNlbGwgd2l0aCB0aGUgc3RhdGUgaW5mb3JtYXRpb24uCgpgYGB7cn0KIAogdWVfcmF0ZV9kYXRhIDwtIGxpc3QuZmlsZXMocmVjdXJzaXZlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgcGF0aCA9ICJkb2NzL1VuZW1wbG95bWVudCIsCiAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiKi54bHN4IiwKICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lcyA9IFRSVUUpICU+JSAKICBtYXAofnJlYWRfeGxzeCguLCBza2lwID0gMTApKQogIApoZWFkKHVlX3JhdGVfZGF0YVsxXSkKYGBgCgpUbyBnZXQgdGhlIHN0YXRlIG5hbWUgZm9yIGVhY2ggZmlsZSB1c2luZyB0aGUgYG1hcCgpYCBmdW5jdGlvbiB0byBwZXJmb3JtIGZ1bmN0aW9ucyBhY3Jvc3MgYWxsIG9mIHRoZSBmaWxlcywgd2Ugd2lsbCBzcGVjaWZpY2FsbHkgaW1wb3J0IG9ubHkgYSBzbWFsbCByYW5nZSBvZiBjZWxscyB1c2luZyB0aGUgYHJhbmdlID0gYCBhcmd1bWVudCBhbmQgdGhlbiBncmFiIHRoZSBjZWxsIHRoYXQgaGFzIHN0YXRlIGluZm9ybWF0aW9uIGJhc2VkIG9uIGl0J3MgbG9jYXRpb24gd2l0aGluIHRoZSByYW5nZSBvZiBjZWxscyBpbXBvcnRlZCB1c2luZyBgYygpYCBhbmQgdGhlbiB1c2UgdGhlIGJhc2UgYHVubGlzdCgpYCBmdW5jdGlvbiB0byB1bmxpc3QgdGhlIGxpc3QgdGhhdCB0aGlzIGNyZWF0ZXMuCgpgYGB7cn0KdWVfcmF0ZV9uYW1lcyA8LSBsaXN0LmZpbGVzKHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHBhdGggPSAiZG9jcy9VbmVtcGxveW1lbnQiLAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIioueGxzeCIsCiAgICAgICAgICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKSAlPiUKICBtYXAofnJlYWRfeGxzeCguLCByYW5nZSA9ICJCNDpCNiIpKSAlPiUKICBtYXAoLiwgYygxLDIpKSAlPiUKICB1bmxpc3QoKQoKdWVfcmF0ZV9uYW1lcwpgYGAKCk5vdyB3ZSB3aWxsIG1ha2UgdGhlc2UgdmFsdWVzIHRoZSBuYW1lcyBvZiB0aGUgZGlmZmVyZW50IHRpYmJsZXMgd2l0aGluIGB1ZV9yYXRlX2RhdGFgLgpgYGB7cn0KbmFtZXModWVfcmF0ZV9kYXRhKSA8LSB1ZV9yYXRlX25hbWVzCmBgYAoKIyMgUG92ZXJ0eSBkYXRhCkV4dHJhY3RlZCBmcm9tIFRhYmxlIDIxIGZyb20gW1VTIENlbnN1cyBCdXJlYXUgUG92ZXJ0eSBEYXRhIF0oaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9kYXRhL3RhYmxlcy90aW1lLXNlcmllcy9kZW1vL2luY29tZS1wb3ZlcnR5L2hpc3RvcmljYWwtcG92ZXJ0eS1wZW9wbGUuaHRtbCkKCkFWT0NhZG8gc3RyYW5nZSBpc3N1ZQoKYGBge3J9CgojKipwZXJzaXN0ZW50IHdhcm5pbmcgZnJvbSB1bmtub3duIG9yaWdpbioqIGh0dHBzOi8vY29tbXVuaXR5LnJzdHVkaW8uY29tL3QvcGVyc2lzdGVudC11bmtub3duLW9yLXVuaW5pdGlhbGlzZWQtY29sdW1uLXdhcm5pbmdzLzY0ODc5Cgojc29sdXRpb24gdG8gYWJvdmUgaXMgYWxsZWRnZWRseTogIkluIGFueSBjYXNlIHRoZSBzdWdnZXN0ZWQgYXBwcm9hY2ggaXMgdG8gaW5pdGlhbGl6ZSB0aGUgY29sdW1uIgoKCnBvdmVydHlfcmF0ZV9kYXRhIDwtIHJlYWRfeGxzKCJkb2NzL1BvdmVydHkvaHN0cG92MjEueGxzIiwgc2tpcD0yKSAjVGhpcyBtYXkgY2F1c2UgaW5pdGlhbGl6YXRpb24gaXNzdWUsIG5vdCBlYXNpbHkgcmVwcm9kdWNpYmxlIChldmVuIGFmdGVyIHJlc3RhcnRpbmcgUikKCmhlYWQocG92ZXJ0eV9yYXRlX2RhdGEpCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoaXMgd2lsbCByZXF1aXJlIHNvbWUgd3JhbmxnaW5nIHRvIG1ha2UgdGhlIGRhdGEgbW9yZSB1c2FibGUuIAoKIyMgVmlvbGVudCBjcmltZQoKVmlvbGVudCBjcmltZSBkYXRhIHdhcyBvYnRhaW5lZCBmcm9tIFtoZXJlXShodHRwczovL3d3dy51Y3JkYXRhdG9vbC5nb3YvU2VhcmNoL0NyaW1lL1N0YXRlL1N0YXRlYnlTdGF0ZS5jZm0pIFRoaXMgZGF0YSBpcyBhIGJpdCB0cmlja2llciBiZWNhdXNlIG9mIHNwYWNlcyBhbmQgYC9gIGluIHRoZSBjb2x1bW4gbmFtZXMsIHRodXMgdGhlIGByZWFkX2xpbmVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVhZHJgIHBhY2thZ2Ugd29ya3MgYmV0dGVyIHRoYW4gdGhlIGByZWFkX2NzdigpYCBmdW5jdGlvbi4KCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZSgiaW1nIiwgImNyaW1lLnBuZyIpKQpgYGAKCmBgYHtyfQpjcmltZV9kYXRhIDwtIHJlYWRfbGluZXMoImRvY3MvQ3JpbWUvQ3JpbWVTdGF0ZWJ5U3RhdGUuY3N2Iiwgc2tpcCA9IDIsIHNraXBfZW1wdHlfcm93cyA9IFRSVUUpCmhlYWQoY3JpbWVfZGF0YSkKCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoaXMgZGF0YSB3aWxsIGFsc28gcmVxdWlyZSBzb21lIHdyYW5sZ2luZyB0byBtYWtlIGl0IG1vcmUgdXNhYmxlLiAKCiMjIFJpZ2h0LXRvLWNhcnJ5IGRhdGEKClRoaXMgZGF0YSBpcyBleHRyYWN0ZWQgZnJvbSB0YWJsZSBpbiBbRG9ub2h1ZSBwYXBlcl0oaHR0cHM6Ly93d3cubmJlci5vcmcvcGFwZXJzL3cyMzUxMC5wZGYpIHt0YXJnZXQ9Il9ibGFuayJ9LiBXZSB3aWxsIHVzZSB0aGUgZnVuY3Rpb24gYHBkZl90ZXh0KClgICBvZiB0aGUgYHBkZnRvb2xzYCBwYWNrYWdlIHRvIGltcG9ydCB0aGUgcGRmIGRvY3VtZW50LgoKYGBge3J9CgppZighZmlsZS5leGlzdHMoaGVyZSgiZG9jcyIsICJ3MjM1MTAucGRmIikpKXsKICB1cmwgPC0gImh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmIgogIHV0aWxzOjpkb3dubG9hZC5maWxlKHVybCwgaGVyZSgiZG9jcyIsICJ3MjM1MTAucGRmIikpCn0KCkRBV3BhcGVyIDwtIHBkZl90ZXh0KGhlcmUoImRvY3MiLCAidzIzNTEwLnBkZiIpKQoKaGVhZChEQVdwYXBlclsxXSkKCmBgYAoKQWdhaW4sIHRoaXMgZGF0YSB3aWxsIGFsc28gcmVxdWlyZSBxdWl0ZSBhIGJpdCBvZiB3cmFuZ2xpbmcuCgoKCiMgKipEYXRhIFdyYW5nbGluZyoqCioqKgojIyBTdGF0ZSBGSVBTIGNvZGVzCgpMZXQncyBmaXJzdCB0YWtlIGEgbG9vayBhdCBvdXIgc3RhdGUgRklQUyBkYXRhIHRvIHNlZSBpZiBpdCBuZWVkcyBhbnkgY2xlYW5pbmcgb3IgcmVzaGFwaW5nLiBXZSBzaG91bGQgc3RhcnQgd2l0aCB0aGlzIGRhdGEsIGJlY3Vhc2Ugd2Ugd2lsbCBuZWVkIHRvIHVzZSBpdCB0byB3cmFuZ2xlIHNvbWUgb2YgdGhlIG90aGVyIGRhdGEuCgpgYGB7cn0KaGVhZChTVEFURV9GSVBTKQpgYGAKCldlIG9ubHkgbmVlZCB0aGUgbGFzdCB0d28gY29sdW1ucywgYnV0IHdlIG1pZ2h0IHdhbnQgdG8gcmVuYW1lIHRoZW0uIFRoZSBgTmFtZWAgdmFyaWFibGUgaXMgdmFndWUuIFRoZSB2YXJpYWJsZSB3aXRoIHRoZSBGSVBTIGNvZGUgaXMgY2FsbGVkIGBTdGF0ZVxuKEZJUFMpYC4gVG8gZ2V0IHJpZCBvZiB0aGUgbmV3IGxpbmUgaW4gdGhpcyB2YXJpYWJsZSBuYW1lIGFuZCB0byBjaGFuZ2UgdGhlIGBOYW1lYCB2YXJpYWJsZSB0byBzb21ldGhpbmcgbW9yZSBpbmZvcm1hdGl2ZSwgd2Ugd2lsbCB1c2UgdGhlIGByZW5hbWUoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gIFRvIHVzZSB0aGlzIGZ1bmN0aW9uLCB3ZSBuZWVkIHRvIGxpc3QgdGhlIG5ldyBuYW1lIGZpcnN0IGZvbGxvd2VkIGJ5IGA9YCBhbmQgdGhlbiB0aGUgZXhpc3RpbmcgdmFyaWFibGUuIFdlIGNhbiByZW5hbWUgbXVsdGlwbGUgdmFyaWFibGVzIGF0IHRoZSBzYW1lIHRpbWUgYnkgdXNpbmcgYSBjb21tYSB0byBzZXBhcmF0ZSB0aGUgdmFyaWFibGVzIHdlIGFyZSByZW5hbWluZy4gV2Ugd2lsbCB1c2UgdGhlIGBzZWxlY3QoKWAgZnVuY3Rpb24gYWxzbyBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIGp1c3QgdG8ga2VlcCB0aGVzZSB2YXJpYWJsZXMsIGFuZCB3ZSB3aWxsIGZpbHRlciBvdXQgdGhlIHJvd3Mgd2l0aCBGSVBTIHZhbHVlcyBvZiBgMDBgIHdpdGggdGhlIGBmaWx0ZXIoKWAgZnVuY3Rpb24sIGFnaWFuIGFsc28gcGFydCBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiB3ZSB3aWxsIHNwZWNpZnkgdGhhdCB3ZSB3YW50IGBTVEFURUZQYCB2YWx1ZXMgdGhhdCBhcmUgbm90IGVxdWFsIHRvIGAwMGAgYnkgdXNpbmcgdGhpcyBvcGVyYXRvcjogYCE9YC4gV2Ugd2lsbCBhbHNvIHVzZSB0aGUgZG91YmxlIHBpcGUgb3BlcmF0b3IgYCU8PiVgIG9mIHRoZSBgbWFncml0dHJgIHBhY2thZ2Ugd2hpY2ggYWxsb3dzIHVzIHRvIHVzZSBkYXRhIGFzIGl1cHV0IGFuZCB0aGVuIHJlYXNzaWduIGl0IGFmdGVyIHdlIHBlZm9ybSBzdW0gZnVuY3Rpb25zIHVzaW5nIGl0LgoKYGBge3J9CgpTVEFURV9GSVBTICU8PiUgCmRwbHlyOjpyZW5hbWUoIFNUQVRFRlAgPSBgU3RhdGVcbihGSVBTKWAsCiAgICAgICAgICAgICAgICAgU1RBVEUgPSBOYW1lKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoU1RBVEVGUCwgU1RBVEUpICU+JQogICAgZHBseXI6OmZpbHRlcihTVEFURUZQICE9ICIwMCIpCgpTVEFURV9GSVBTCgpgYGAKCiMjIERlbW9ncmFwaGljIGFuZCBwb3B1bGF0aW9uIGRhdGEKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byBzZWUgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgaG93IHRoZSBkZW1vZ3JwaGljIGRhdGEgd2FzIHdyYW5nbGVkIDwvc3VtbWFyeT4KCgo8Zm9udCBzaXplPSI2Ij4gKioxOTc3LTE5NzkqKjwvZm9udD4KCioqKgoKCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBvdXIgZGVtb2dyYXBoaWMgZGF0YSBhY3Jvc3MgdGhlIGRlY2FkZXMgdGhhdCB3ZSB3aXNoIHRvIHN0dWR5LiBJZiB5b3UgaGF2ZSB2ZXJ5IHdpZGUgZGF0YSAobWVhbmluZyBpdCBoYXMgbWFueSBjb2x1bW5zKSwgb25lIHdheSB0byB2aWV3IHRoZSBkYXRhIHNvIHRoYXQgeW91IGNhbiBzZWUgYWxsIG9mIHRoZSBjb2x1bW5zIGF0IHRoZSBzYW1lIHRpbWUgaXMgdG8gdXNlIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiAKClRha2luZyBhIGxvb2sgYXQgdGhlIGZpcnN0IGRlY2FkZSBvZiBkYXRhLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGBSYWNlL1NleCBJbmRpY2F0b3JgIGNvbnRhaW5zIHR3byB0eXBlcyBvZiBkYXRhLCB0aGUgcmFjZSBhbmQgdGhlIHNleC4gVGhpcyBkb2VzIG5vdCBmb2xsb3cgdGhlIHRpZHkgZGF0YSBwaGlsb3NvcGh5LCB3aGVyZSBlYWNoIGNlbGwgb2YgYSB0aWJibGUgc2hvdWxkIG9ubHkgY29udGFpbiBvbmUgcGllY2Ugb2YgaW5mb3JtYXRpb24uIFR5cGljYWxseSBvbmUgbWlnaHQgdGhpbmsgb2YgdXNpbmcgdGhlIGBzZXBhcmF0ZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlIHRvIHNwbGl0IHRoaXMgdmFyaWFibGUgaW50byB0d28uIEhvd2V2ZXIsIG9uZSBvZiB0aGUgcmFjZSB2YWx1ZXMgaXMgYE90aGVyIHJhY2VzYCBhbmQgc2luY2UgdGhpcyBhbHNvIGhhcyBhIHNwYWNlLCB0aGlzIG1ha2VzIHNlcGFyYXRpbmcgdGhpcyBkYXRhIG1vcmUgdHJpY2t5LgoKSW5zdGVhZCB3ZSB3aWxsIHVzZSB0aGUgYHN0cl9leHRyYWN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZSBhbmQgdGhlIGBtdXRhdGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gVGhlICJtdXRhdGUoKSIgd2lsbCBhbGxvdyB1cyB0byBjcmVhdGUgbmV3IHZhcmlhYmxlcywgYW5kICJzdHJfZXh0cmFjdCgpIiBmdW5jdGlvbiAgd2lsbCBhbGxvdyB1cyB0byBtYXRjaCBzcGVjaWZpYyBwYXR0ZXJucyBhbmQgcHVsbCBvdXQgbWF0Y2hlcyB0byB0aG9zZSBwYXR0ZXJucy4gVGhlcmVmb3JlLCBpZiB0aGUgYFJhY2UvU2V4IEluZGljYXRvcmAgdmFsdWUgaXMgYE90aGVyIHJhY2VzIG1hbGVgIGFuZCBpZiB3ZSBleHRyYWN0IHBhdHRlcm5zIG1hdGNoaW5nIGVpdGhlciBgIm1hbGUiYCBvciBgImZlbWFsZSJgIHdoaWNoIHdlIGNhbiBzcGVjaWZ5IGxpa2UgdGhpcyBgcGF0dGVybiA9ICJtYWxlfGZlbWFsZSJgIHRoZW4sIHRoZSB2YWx1ZSB3aWxsIGJlIGBtYWxlYC4KCkZpcnN0IHdlIG5lZWQgdG8gcmVuYW1lIHRoZSBgUmFjZS9TZXggSW5kaWNhdG9yYCB2YXJhaWJsZSB0byBub3QgaGF2ZSBzcGFjZXMgc28gdGhhdCBpdCBpcyBjb21wYXRpYmxlIHdpdGggdGhlIGBzdHJfZXh0cmFjdCgpYCBmdW5jdGlvbi4KCldlIGFsc28gd2FudCB0byByZW5hbWUgYSBjb3VwbGUgb2YgdmFyaWFibGVzIHRvIGJlIHNpbXBsZXIgYW5kIGZpbHRlciB0aGUgZGF0YSB0byBvbmx5IGluY2x1ZGUgdGhlIHllYXJzIG9mIHRoZSBkYXRhIHdlIGFyZSBpbnRlcmVzdGVkIGluLCBhcyB3ZWxsIGFzIHJlbW92ZSBzb21lIHZhcmlhYmxlcyB0aGF0IHdlIGRvbnQgbmVlZCBsaWtlIHRoZSBgRklQUyBTdGF0ZSBDb2RlYC4gV2UgY2FuIHJlbW92ZSB2YXJpYWJsZXMgYnkgdXNpbmcgdGhlIGBzZWxlY3QoKWAgZnVuY3Rpb24gd2l0aCBhIGAtYCBtaW51cyBzaWduIGluIGZyb250IG9mIHRoZSB2YXJpYWJsZSB3ZSB3aXNoIHRvIHJlbW92ZS4KCmBgYHtyfQpkcGx5cjo6Z2xpbXBzZShkZW1fNzdfNzkpCgoKZGVtXzc3Xzc5IDwtIGRlbV83N183OSAlPiUKICByZW5hbWUoInJhY2Vfc2V4IiA9YFJhY2UvU2V4IEluZGljYXRvcmApICU+JQogIG11dGF0ZShTRVggPSBzdHJfZXh0cmFjdChyYWNlX3NleCwgIm1hbGV8ZmVtYWxlIiksCiAgICAgICAgUkFDRSA9IHN0cl9leHRyYWN0KHJhY2Vfc2V4LCAiQmxhY2t8V2hpdGV8T3RoZXIiKSklPiUKICBzZWxlY3QoLWBGSVBTIFN0YXRlIENvZGVgLCAtYHJhY2Vfc2V4YCkgJT4lCiAgcmVuYW1lKCJZRUFSIiA9IGBZZWFyIG9mIEVzdGltYXRlYCwKICAgICAgICAiU1RBVEUiID0gYFN0YXRlIE5hbWVgKSAlPiUKICBmaWx0ZXIoWUVBUiAlaW4lIDE5Nzc6MTk3OSkKCmdsaW1wc2UoZGVtXzc3Xzc5KQpgYGAKClRoYXQncyBsb29raW5nIHByZXR0eSAgZ29vZCEgV2UgYWxzbyB3YW50IHRvIHRha2UgYWxsIHRoZSBhZ2UgZ3JvdXAgdmFyaWFiZWxzIGFuZCBtYWtlIG9uZSB2YXJpYWJsZSB0aGF0IGlzIHRoZSBhZ2UgZ3JvdXAgbmFtZSBhbmQgb25lIHRoYXQgaXMgdGhlIHZhbHVlIG9mIHRoZSBwb3B1bGF0aW9uIGNvdW50IGZvciB0aGF0IGFnZSBncm91cC4gVG8gZG8gdGhpcyB3ZSB3aWxsIHVzZSB0aGUgYHBpdm90X2xvbmdlcigpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlLiBUbyB1c2UgdGhpcyBmdW5jdGlvbiwgd2UgbmVlZCB0byB1c2UgdGhlIGBjb2xzYCBhcmd1bWVudCB0byBpbmRpY2F0ZSB3aGljaCBjb2x1bW5zIHdlIHdhbnQgdG8gcGl2b3QuIFdlIGFsc28gbmFtZSB0aGUgbmV3IHZhcmlhYmxlcyB3ZSB3aWxsIGNyZWF0ZSB3aXRoIHRoZSBgbmFtZXNfdG9gIGFuZCBgdmFsdWVzX3RvYCBhcmd1bWVudHMuIFRoZSBgbmFtZXNfdG9gIHdpbGwgYmUgdGhlIG5hbWUgb2YgdGhlIHZhcmlhYmxlIHRoYXQgd2lsbCBpZGVudGlmeSBlYWNoIGFnZSBncm91cCBhbmQgYHZhbHVlc190b2Agd2lsbCBiZSB0aGUgbmFtZSBvZiB0aGUgdmFyaWFibGUgdGhhdCBjb250YWlucyB0aGUgY29ycmVzcG9uZGluZyBwb3B1bGF0aW9uIHZhbHVlcy4KYGBge3J9CmRlbV83N183OSA8LSBkZW1fNzdfNzkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHM9Y29udGFpbnMoInllYXJzIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIkFHRV9HUk9VUCIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJTVUJfUE9QIikKCmdsaW1wc2UoZGVtXzc3Xzc5KQpgYGAKCldlIGFsc28gd2FudCB0byBnZXQgZGF0YSBhYm91dCB0aGUgdG90YWwgcG9wdWxhdGlvbiBmb3IgdGhlIHN0YXRlIGZvciBlYWNoIHllYXIuCgpUbyBkbyBzbyB3ZSBjYW4gc3VtIGFsbCB0aGUgdmFsdWVzIGZvciB0aGUgYFNVQl9QT1BgIHZhcmlhYmxlIHRoYXQgd2UganVzdCBjcmVhdGVkLiBUbyBkbyB0aGlzIHdlIGNhbiB1c2UgdGhlIGBncm91cF9ieWAgYW5kIGBzdW1tYXJpc2UoKWAgZnVuY3Rpb25zIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFRoZSBgZ3JvdXBfYnkoKWAgZnVuY3Rpb24gc3BlY2lmaWVzIGhvdyB3ZSB3YW50IHRvIGNhbGN1bGF0ZSAgb3VyIHN1bSwgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIGNhbGN1bGF0ZSBpdCBmb3IgZWFjaCB5ZWFyIGFuZCBlYWNoIHN0YXRlIGluZGl2aWR1YWxseS4gVGh1cywgYWxsIHRoZSB2YWx1ZXMgdGhhdCBoYXZlIHRoZSBzYW1lIGBTVEFURWAgYW5kIGBZRUFSYCB2YWx1ZXMgd2lsbCBiZSBzdW1tZWQgdG9nZXRoZXIsIHJhdGhlciB0aGFuIHN1bW1pbmcgdXNpbmcgYWxsIG9mIHRoZSB2YWx1ZXMgaW4gdGhlIGBTVUJfUE9QYCB2YXJpYWJsZS4gVGhlIGAuZ3JvdXBzYCBhcmd1bWVudCBhbGxvd3MgdXMgdG8gcmVtb3ZlIHRoZSBncm91cGluZyBhZnRlciB3ZSBwZWZvcm0gdGhlIGNhbGN1bGF0aW9uIHdpdGggYHN1bW1hcmlzZSgpYC4KCmBgYHtyfQpwb3BfNzdfNzkgPC0gZGVtXzc3Xzc5ICU+JQogIGdyb3VwX2J5KFlFQVIsIFNUQVRFKSAlPiUKICBzdW1tYXJpc2UoIlRPVF9QT1AiID0gc3VtKFNVQl9QT1ApLCAuZ3JvdXBzID0gImRyb3AiKSAKCnBvcF83N183OSAKYGBgCgoKIE5vdyB3ZSB3aWxsIGFkZCB0aGUgcG9wdWxhdGlvbiB2YWx1ZSB0byB0aGUgZGVtb2dyYXBoaWMgdGliYmxlIHVzaW5nIHRoZSBgbGVmdF9qb2luKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIEl0IGlzIGltcG9yYW50IHRoYXQgd2Ugc3BlY2lmeSBob3cgdGhpcyBzaG91bGQgYmUgZG9uZSwgdGhhdCB0aGUgYFlFQVJgIGFuZCBgU1RBVEVgIHZhcmlhYmxlIHZsYXVlcyBzaG91bGQgbWF0Y2ggZWFjaG90aGVyLiBUaGlzIHdpbGwgcGxhY2UgdGhlIGBkZW1fNzdfNzlgIHZhcmlhYmxlcyB0byB0aGUgbGVmdCBvZiB0aGUgYHBvcF83N183OWAgZGF0YS4gCiAKYGBge3J9CmRlbV83N183OSA8LSBkZW1fNzdfNzkgJT4lCiAgbGVmdF9qb2luKHBvcF83N183OSwgYnkgPSBjKCJZRUFSIiwiU1RBVEUiKSkKCmRlbV83N183OQpgYGAKCldlIHdpbGwgYWxzbyBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2UgdGhhdCBlYWNoIGdyb3VwIG1ha2VzIHVwIG9mIHRoZSB0b3RhbCBwb3B1bGF0aW9uLCBieSBkaXZpZGluZyB0aGUgYFNVQl9QT1BgIGJ5IHRoZSBgVE9UX1BPUGAgYW5kIG11bHRpcGx5aW5nIGJ5IDEwMCB1c2luZyB0aGUgYG11dGF0ZSgpYCBmdW5jdGlvbi4gd2Ugd2lsbCBhbHNvIHJlbW92ZSB0aGUgb3RoZXIgcG9wdWxhdGlvbiB2YXJpYWJsZXMuCgpgYGB7cn0KZGVtXzc3Xzc5ICU8PiUKICBtdXRhdGUoUEVSQ19TVUJfUE9QID0gKFNVQl9QT1AvVE9UX1BPUCkqMTAwKSAlPiUKICBzZWxlY3QoLVNVQl9QT1AsIC1UT1RfUE9QKQoKZGVtXzc3Xzc5CmBgYApJdCBpcyBpbXBvcnRhbnQgdG8gbWFrZSBzdXJlIHRoYXQgd2UgaGF2ZSB0aGUgdG90YWwgdmFsdWVzIHdlIHdvdWxkIGV4cGVjdC4gV2UgaGF2ZSB0d28gbGV2ZWxzIG9mIGBTRVhgLCB0aHJlZSBsZXZlbHMgb2YgYFJhY2VgLCB0aHJlZSBsZXZlbHMgb2YgYFlFQVJgLCBlaWdodGVlbiBsZXZlbHMgb2YgYEFHRV9HUk9VUGAsIGFuZCBmaWZ0eSBvbmUgbGV2ZWxzIG9mIGBTVEFURWAuIElmIHdlIG11bHRpcGx5IHRoaXMgdG9nZXRoZXIgd2UgZ2V0IDE2LDUyNCB3aGljaCBpcyB0aGUgc2FtZSBhcyB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gb3VyIGZpbmFsIGBkZW1fNzdfNzlgIGRhdGEuIExvb2tzIGdvb2QhCgpBbHNvIExldCdzIG1ha2UgdGhlIHZhbHVlcyBvZiB0aGUgYFNFWGAgdmFyaWFibGUgY2FwYXRhbGl6ZWQgc28gdGhhdCB0aGV5IG1hdGNoIHRoZSBvdGhlciB2YWx1ZXMgb2YgdGhlIG90aGVyIHZhcmlhYmxlcyBsaWtlIGBSQUNFYCBldGMuIFRoaXMgd2lsbCBoZWxwIHVzIHRvIGtlZXAgY29uc2lzdGVudCB2YWx1ZXMgYWNyb3NzIHRoZSBkaWZmZXJlbnQgeWVhcnMgYXMgd2Ugd3JhbmdsZSB0aGUgZGF0YSBmb3IgdGhlIG90aGVyIGRlY2FkZXMuIFRvIGRvIHNvIHdlIHdpbGwgdXNlIHRoZSBgc3RyX3RvX3RpdGxlKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZS4gV2UgbmVlZCB0byB1c2UgdGhlIGBwdWxsKClgIGZ1bmN0aW9uIHRvIGdldCB0aGUgdmFsdWVzIG9mIGBTRVhgIG91dCBvZiBgZGVtXzc3Xzc5YC4gT25jZSB3ZSBtYWtlIHRoZW0gY2FwdGlhbGl6ZWQgdGhleSBhcmUgdGhlbiByZWFzaWduZWQgdG8gdGhlIGBTRVhgIHZhcmlhYmxlLiAKCmBgYHtyfQoKZGVtXzc3Xzc5ICU8PiUKICBtdXRhdGUoU0VYID0gc3RyX3RvX3RpdGxlKHB1bGwoZGVtXzc3Xzc5LCBTRVgpKSkKCiMgVGhpcyBjYW4gYWxzbyBiZSBkb25lIGxpbmUgdGhpczoKZGVtXzc3Xzc5ICU8PiUKICBtdXRhdGUoU0VYID0gc3RyX3RvX3RpdGxlKHB1bGwoLiwgU0VYKSkpCmBgYAoKPGZvbnQgc2l6ZT0iNiI+ICoqMTk4MC0xOTg5Kio8L2ZvbnQ+CgoqKioKCgpGb3IgdGhpcyBkZWNhZGUgZWFjaCB5ZWFyIGlzIGEgc2VwYXJhdGUgdGliYmxlIGFuZCB0aGV5IGFyZSBjb21iaW5lZCBhcyBhIGxpc3QuCmBgYHtyfQpjbGFzcyhkZW1fODBfODkpCmBgYAoKU28gdGhlIGZpcnN0IHRoaW5nIHdlIG5lZWQgdG8gZG8gaXMgY29tYmluZSBlYWNoIHRpYmJsZSBvZiB0aGUgbGlzdCB0b2dldGhlci4gV2UgY2FuIGRvIHRoYXQgdXNpbmcgdGhlIGBiaW5kX3Jvd3MoKWAgZnVuY3Rpb24gb2YgYGRwbHlyYCB3aGljaCBhcHBlbmRzIHRoZSBkYXRhIHRvZ2V0aGVyIGJhc2VkIG9uIHRoZSBwcmVzZW5jZSBvZiBjb2x1bW5zIHdpdGggdGhlIHNhbWUgbmFtZSBpbiB0aGUgZGlmZmVyZW50IHRpYmJsZXMuIFdlIHdpbGwgdXNlIHRoZSBgbWFwX2RmKClgIGZ1bmN0aW9uIG9mIHRoZSBgcHVycnJgIHBhY2thZ2UgdG8gYWxsb3cgdXMgdG8gZG8gdGhpcyBhY3Jvc3MgZWFjaCB0aWJibGUgaW4gb3VyIGxpc3QuIAoKYGBge3J9CmRlbV84MF84OSA8LSBkZW1fODBfODkgJT4lCiAgbWFwX2RmKGJpbmRfcm93cykKCmdsaW1wc2UoZGVtXzgwXzg5ICkKYGBgCgpHcmVhdCEgTm93IG91ciBkYXRhIGlzIGFsbCB0b2dldGhlci4KCk5vdyB3ZSB3aWxsIHdyYW5nbGUgdGhlIGRhdGEgc2ltaWxhcmx5IHRvIHRoZSBwcmV2aW91cyBkZWNhZGUuCmBgYHtyfQpkZW1fODBfODkgPC0gZGVtXzgwXzg5ICU+JQogIHJlbmFtZSgicmFjZV9zZXgiID1gUmFjZS9TZXggSW5kaWNhdG9yYCkgJT4lCiAgbXV0YXRlKFNFWCA9IHN0cl9leHRyYWN0KHJhY2Vfc2V4LCAibWFsZXxmZW1hbGUiKSwKICAgICAgICBSQUNFID0gc3RyX2V4dHJhY3QocmFjZV9zZXgsICJCbGFja3xXaGl0ZXxPdGhlciIpKSU+JQogIHNlbGVjdCggLWByYWNlX3NleGApICU+JQogIHJlbmFtZSgiWUVBUiIgPSBgWWVhciBvZiBFc3RpbWF0ZWApCiAgICAgICAgIApnbGltcHNlKGRlbV84MF84OSkKYGBgCk5vdGljZSB0aGF0IHRoaXMgdGltZSB0aGUgc3RhdGUgaW5mb3JtYXRpb24gaXMgYmFzZWQgb24gdGhlIG51bWVyaWMgRklQUyB2YWx1ZS4gV2Ugd2FudCBvbmx5IHRoZSBmaXJzdCB0d28gdmFsdWVzLCBhcyB0aGUgcmVzdCBpbmRpY2F0ZSB0aGUgY291bnR5LiBXZSBjYW4gdXNlIHRoZSBgc3RyX3N1YigpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgZm9yIHRoaXMuIFdlIHdpbGwgc3BlY2lmeSB0aGF0IHdlIHdhbnQgdG8gc3RhcnQgYXQgdGhlIGZpcnN0IHBvc2l0aW9uIGFuZCBlbmQgYXQgdGhlIHNlY29uZC4gIEp1c3QgbGlrZSBgc3RyX2V4dHJhY3QoKWAgd2UgbmVlZCB0byByZW5hbWUgdGhpcyB2YXJpYWJsZSBmaXJzdCBzbyB0aGF0IGl0IGlzIGNvbXBhdGlibGUuIApgYGB7cn0KZGVtXzgwXzg5ICU8PiUKcmVuYW1lKCJTVEFURUZQX3RlbXAiID0gIkZJUFMgU3RhdGUgYW5kIENvdW50eSBDb2RlcyIpICU+JQptdXRhdGUoU1RBVEVGUCA9IHN0cl9zdWIoU1RBVEVGUF90ZW1wLCBzdGFydCA9IDEsIGVuZCA9IDIpKSAlPiUKICAgIGxlZnRfam9pbihTVEFURV9GSVBTLCBieSA9ICJTVEFURUZQIikgJT4lCiAgZHBseXI6OnNlbGVjdCgtU1RBVEVGUCkKCmdsaW1wc2UoZGVtXzgwXzg5KQpgYGAKCgpgYGB7cn0KZGVtXzgwXzg5ICU8PiUKICBwaXZvdF9sb25nZXIoY29scz1jb250YWlucygieWVhcnMiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiQUdFX0dST1VQIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlNVQl9QT1BfdGVtcCIpICU+JQogIGdyb3VwX2J5KFlFQVIsIFNUQVRFLCBBR0VfR1JPVVAsIFNFWCwgUkFDRSkgJT4lCiAgc3VtbWFyaXNlKFNVQl9QT1AgPSBzdW0oU1VCX1BPUF90ZW1wKSwgLmdyb3Vwcz0iZHJvcCIpCgpkZW1fODBfODkKYGBgCiAgCmBgYHtyfQpwb3BfODBfODkgPC0gZGVtXzgwXzg5ICU+JQogIGdyb3VwX2J5KFlFQVIsIFNUQVRFKSAlPiUKICBzdW1tYXJpc2UoIlRPVF9QT1AiID0gc3VtKFNVQl9QT1ApLCAuZ3JvdXBzID0gImRyb3AiKSAKCgpkZW1fODBfODkgPC0gZGVtXzgwXzg5ICU+JQogIGxlZnRfam9pbihwb3BfODBfODksIGJ5ID0gYygiWUVBUiIsIlNUQVRFIikpICU+JQogIG11dGF0ZShQRVJDX1NVQl9QT1AgPSAoU1VCX1BPUC9UT1RfUE9QKSoxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoLVNVQl9QT1AsIC1UT1RfUE9QKQoKZGVtXzgwXzg5CmBgYAoKSnVzdCBsaWtlIHdpdGggdGhlIGRhdGEgZnJvbSB0aGUgNzBzIHdlIHdpbGwgYWxzbyBjaGFuZ2UgdGhlIHZhbHVlcyBmb3IgYFNFWGAgdG8gYmUgY2FwaXRhbGl6ZWQuCgpgYGB7cn0KZGVtXzgwXzg5ICU8PiUKICBtdXRhdGUoU0VYID0gc3RyX3RvX3RpdGxlKHB1bGwoLiwgU0VYKSkpCmBgYAoKQWdhaW4sIGl0IGlzIGltcG9ydGFudCB0byBtYWtlIHN1cmUgdGhhdCB3ZSBoYXZlIHRoZSB0b3RhbCB2YWx1ZXMgd2Ugd291bGQgZXhwZWN0LiBUaGlzIHRpbWUgd2UgaGF2ZTogdHdvIGxldmVscyBvZiBgU0VYYCwgdGhyZWUgbGV2ZWxzIG9mIGBSYWNlYCwgdGVuIGxldmVscyBvZiBgWUVBUmAsIGVpZ2h0ZWVuIGxldmVscyBvZiBgQUdFX0dST1VQYCwgYW5kIGZpZnR5IG9uZSBsZXZlbHMgb2YgYFNUQVRFYC4KCklmIHdlIG11bHRpcGx5IHRoZXNlIHRvZ2V0aGVyIHdlIGdldCA1NSwwODAsIHdoaWNoIGlzIHRoZSBzYW1lIGFzIHRoZSBudW1iZXIgb2Ygcm93cyBvZiB0aGUgZmluYWwgYGRlbV84MF84OWAgZGF0YS4gTG9va3MgZ29vZCEKCjxmb250IHNpemU9IjYiPiAqKjE5OTAtMTk5OSoqPC9mb250PgoKKioqCgpKdXN0IGxpa2UgdGhlIDgwcyB3ZSBuZWVkIHRvIGNvbWJpbmUgdGhlIGRhdGEgYWNyb3NzIHRoZSBmaWxlczoKCmBgYHtyfQpkZW1fOTBfOTkgPC0gZGVtXzkwXzk5ICU+JQogIG1hcF9kZihiaW5kX3Jvd3MpCmBgYAoKYGBge3J9CmdsaW1wc2UoZGVtXzkwXzk5KQpgYGAKRm9yIHRoaXMgZGVjYWRlIHRoZSBjb2x1bW4gbmFtZXMgY2FuJ3QgYWxsIGJlIGltcG9ydGVkIGluIGEgc2ltcGxlIHdheSBmcm9tIHRoZSB0YWJsZSwgc28gdGhleSBuZWVkIHRvIGJlIHJlY29kZWQuCgpIZXJlIGlzIHdoYXQgdGhlIGRhdGEgbG9va3MgbGlrZSBiZWZvcmUgaW1wb3J0aW5nOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICI5MC5wbmciKSkKYGBgCgpTbywgZmlyc3QgdXNpbmcgdGhlIGJhc2UgYGNvbG5hbWVzKClgIGZ1bmN0aW9uIHdlIGNoYW5nZSB0aGUgbmFtZXMgb2YgdGhlIGNvbHVtbiBuYW1lcy4KCmBgYHtyfQoKY29sbmFtZXMoZGVtXzkwXzk5KSA8LSBjKCJZRUFSIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJTVEFURUZQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJBZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgIk5IX1dfTSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiTkhfV19GIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJOSF9CX00iLAogICAgICAgICAgICAgICAgICAgICAgICAgIk5IX0JfRiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiTkhfQUlBTl9NIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJOSF9BSUFOX0YiLAogICAgICAgICAgICAgICAgICAgICAgICAgIk5IX0FQSV9NIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJOSF9BUElfRiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiSF9XX00iLAogICAgICAgICAgICAgICAgICAgICAgICAgIkhfV19GIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJIX0JfTSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiSF9CX0YiLAogICAgICAgICAgICAgICAgICAgICAgICAgIkhfQUlBTl9NIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJIX0FJQU5fRiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiSF9BUElfTSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiSF9BUElfRiIpCgpnbGltcHNlKGRlbV85MF85OSkKYGBgCgpOb3RpY2UgYWxzbyB0aGF0IHRoZSBmaXJzdCByb3cgaXMgYWxsIGBOQWAgdmFsdWVzIGZyb20gd2hpdGUgc3BhY2UgaW4gdGhlIG9yZ2luYWwgdGFibGUgZm9yIDE5OTAsIHRoaXMgaXMgcHJvYmFibHkgdHJ1ZSBmb3IgZWFjaCB5ZWFyLiBXZSBjYW4gY2hlY2sgdGhlbSBkaW1lbnNpb25zIG9mIG91ciB0YWJsZSB1c2luZyB0aGUgYmFzZSBgZGltKClgIGZ1bmN0aW9uLiBXaGVuIHdlIGZpbHRlciBmb3Igcm93cyB3aGVyZSBgWUVBUmAgaXMgYE5BYCwgd2UgaW5kZWVkIHNlZSAxMCByb3dzLCB3aGljaCBpcyB3aGF0IHdlIHdvdWxkIGV4cGVjdCBpZiB3ZSBoYXZlIGEgcm93IGxpa2UgdGhpcyBmb3IgZWFjaCBvZiB0aGUgeWVhcnMgaW4gdGhlIGRlY2FkZS4gV2Ugc2VlIHRoZSBzYW1lIGlmIHdlIHRyeSBhIGRpZmZlcmVudCB2YXJpYWJsZS4gTm93IHdlIHdpbGwgdGVzdCB0byBzZWUgaG93IGxhcmdlIG91ciB0aWJibGUgaXMgaWYgd2UgZHJvcCByb3dzIHdpdGggYE5BYCB2YWx1ZXMgdXNpbmcgdGhlIGBkcm9wX25hKClgIGZ1bmN0aW9uIG9mIGB0aWR5cmAuIFdlIHRoYXQgaW5kZWVkIG91ciBkaW1lbnNpb25zIG9ubHkgY2hhbmdlZCBieSB0ZW4sIHNvIHRoZXJlIGFyZSBub3Qgb3RoZXIgcm93cyB3aXRoIG1pc3NpbmcgdmFsdWVzIHRoYXQgd2UgbWlnaHQgbm90IGV4cGVjdC4gU28gbm93IHdlIHdpbGwgcmVzaWduIHRoZSBgZGVtXzkwXzk5YCB2YXJpYWJsZSBhZnRlciByZW1vdmluZyB0aGVzZSByb3dzLgoKYGBge3J9CgpkaW0oZGVtXzkwXzk5KQoKZGVtXzkwXzk5ICU+JQogIGZpbHRlcihpcy5uYShZRUFSKSkKCmRlbV85MF85OSAlPiUKICBmaWx0ZXIoaXMubmEoQWdlKSkgCgpkZW1fOTBfOTkgJT4lZHJvcF9uYSgpIAoKZGVtXzkwXzk5ICU8PiVkcm9wX25hKCkgCmBgYAoKVGhlbiB3ZSBzdW0gYWNyb3NzIHRoZSBub25oaXNwYW5pYyBhbmQgaGlzcGFuaW5jIGdyb3VwcyBiZWNhdXNlIHRoaXMgaW5mb3JtYXRpb24gaXMgbm90IGF2YWlsYWJsZSBmb3IgdGhlIG90aGVyIHByZXZpb3VzIGRlY2FkZXMuIFRoZW4gd2Ugd2lsbCByZW1vdmUgdGhlIHZhcmlhYmxlcyBmb3IgdGhlIGhpc3BhbmljIGFuZCBub25oaXNwYW5pYyBzdWJncm91cHMgdXNpbmcgYHNlbGVjdCgpYC4KCmBgYHtyfQoKZGVtXzkwXzk5JTw+JQogICAgbXV0YXRlKFdfTSA9IE5IX1dfTSArIEhfV19NLAogICAgICAgICAgIFdfRiA9IE5IX1dfRiArIEhfV19GLAogICAgICAgICAgIEJfTSA9IE5IX0JfTSArIEhfQl9NLAogICAgICAgICAgIEJfRiA9IE5IX0JfRiArIEhfQl9GLAogICAgICAgICAgIEFJQU5fTSA9IE5IX0FJQU5fTSArIEhfQUlBTl9NLAogICAgICAgICAgIEFJQU5fRiA9IE5IX0FJQU5fRiArIEhfQUlBTl9GLAogICAgICAgICAgIEFQSV9NID0gTkhfQVBJX00gKyBIX0FQSV9NLAogICAgICAgICAgIEFQSV9GID0gTkhfQVBJX0YgKyBIX0FQSV9GKSAlPiUKICBzZWxlY3QoLXN0YXJ0c193aXRoKCJOSF8iKSwgLXN0YXJ0c193aXRoKCJIXyIpKQoKZ2xpbXBzZShkZW1fOTBfOTkpCmBgYAoKTG9va2luZyBiZXR0ZXIhIFdlIGFsc28gbmVlZCB0byBhZGQgYWdlIGdyb3VwcyBsaWtlIHRoZSBvdGhlciBkZWNhZGVzLiBXZSB3aWxsIHRha2UgYSBsb29rIGF0IHRoZSA4MHMgZGF0YSB1c2luZyB0aGUgYGRpc3RpbmN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gc2VlIHdoYXQgYWdlIGdyb3VwcyB3ZSBuZWVkLiBXZSBjYW4gdXNlIHRoZSBiYXNlIGBjdXQoKWAgZnVuY3Rpb24gdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHdpdGggYG11dGF0ZSgpYCBjYWxsZWQgYEFHRV9HUk9VUGAgdGhhdCB3aWxsIGhhdmUgYSBsYWJlbCBmb3IgZXZlcnkgY2hhbmdlIGluIDUgeWVhcnMgb2YgYWdlLiBUaGUgYHJpZ2h0ID0gRkFMU0VgIGFyZ3VtZW50IHNwZWNpZmllcyB0aGF0IHRoZSBpbnRlcnZhbCBpcyBub3QgY2xvc2VkIG9uIHRoZSByaWdodCwgbWVhbmluZyB0aGF0IGlmIHRoZSB2YWx1ZSBpcyBhdCB0aGUgY3V0cG9pbnQgbGlrZSB0aGUgYEFnZWAgdmFsdWUgaXMgNSwgdGhlbiBpdCB3aWxsIGJlIGluIHRoZSBgNSB0byA5IHllYXJzYCBncm91cC4KCldlIGNhbiBtYWtlIHRoZSBsYWJlbHMgZm9yIHRoZSBgQUdFX0dST1VQYCB2YXJpYWJsZSBtYXRjaCB0aG9zZSBvZiBgZGVtXzc3Xzc5YCBidXQgd2UgbmVlZCB0byBwdWxsIG91dCB0aGUgdmFsdWVzIG9mIHRoZSB0aWJibGUgY3JlYXRlZCBieSBgZGlzdGluY3QoKWAuIFRvIGRvIHRoaXMgd2UgY2FuIHVzZSB0aGUgYHB1bGwoKWAgZnVuY3Rpb24gZnJvbSB0aGUgYGRwbHlyYCBwYWNrYWdlLiBOb3RlIHRoYXQgaXQgaXMgaW1wb3J0YW50IHRvIGNoZWNrIHRoYXQgdGhlIGBBR0VfR1JPVVBgIHZhbHVlcyBhcmUgbGlzdGVkIGluIG9yZGVyIGZvciBgZGVtXzc3Xzc5YC4gV2Ugd2lsbCBhbHNvIHJlbW92ZSB0aGUgYEFnZWAgdmFyaWFibGUgYWZ0ZXIgd2UgY3JlYXRlIHRoZSBuZXcgYEFHRV9HUk9VUGAgdmFyaWFibGUgZm9yIHRoZSBgZGVtXzkwXzk5YCBkYXRhLiAKCgpgYGB7cn0KCmRpc3RpbmN0KGRlbV83N183OSwgQUdFX0dST1VQKQpwdWxsKGRpc3RpbmN0KGRlbV83N183OSwgQUdFX0dST1VQKSkKCmRlbV85MF85OSAlPD4lCiAgbXV0YXRlKEFHRV9HUk9VUCA9IGN1dChBZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCw5MCwgYnk9NSksCiAgICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IEZBTFNFLCBsYWJlbHMgPSBwdWxsKGRpc3RpbmN0KGRlbV83N183OSxBR0VfR1JPVVApLCBBR0VfR1JPVVApKSkgJT4lCiAgc2VsZWN0KC1BZ2UpCgpnbGltcHNlKGRlbV85MF85OSkKCmBgYAoKTGlrZSB0aGUgcHJldmlvdXMgZGVjYWRlcyB3ZSB3aWxsIGNyZWF0ZSBhIGBSQUNFYCBhbmQgYFNVQl9QT1BgIHZhcmlhYmxlIHVzaW5nIGBwaXZvdF9sb25nZXIoKWAgdG8gY3JlYXRlIGEgc2luZ2xlIGBSYWNlYCB2YXJpYWJsZSBvdXQgb2YgYWxsIHRoZSBzdWJncm91cCB2YXJpYWJsZXMuIAoKTm93IHdlIG5lZWQgdG8gY29sbGFwc2UgdGhlIGRhdGEgZm9yIHRoZSB2YXJpb3VzIHJhY2VzIHNvIHRoYXQgaXQgbWF0Y2hlcyB0aGUgcHJldmlvdXMgZGVjYWRlcy4gVGhpcyB0aW1lIHdlIHdpbGwgdXNlIHRoZSBgY2FzZV93aGVuKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgYW5kIHRoZSBgc3RyX2RldGVjdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgdG8gaWRlbnRpZnkgd2hlbiB0aGUgcmFjZSBpcyBzb21ldGhpbmcgb3RoZXIgdGhhbiBgQmAgb3IgYFdgIGFuZCByZXBsYWNlIHdpdGggdGhlIHZhbHVlIGBPdGhlcmAuIFRoZSB2YWx1ZSB0byB0aGUgcmlnaHQgb2YgdGhlIGB+YCBpbmRpY2F0ZXMgd2hhdCB3ZSB3YW50IHRoZSB2YWx1ZSBvZiB0aGUgbmV3IHZhcmlhYmxlIHRvIGJlIGlmIHRoZSB2YWx1ZSBvZiB0aGUgdmFyaWFibGUgd2UgYXJlIHVzaW5nIHdpdGggYHN0cl9kZWNlY3QoKWAgbWF0Y2hlcyB0aGUgY29uZGl0aW9uIHNwZWNpZmllZC4gSWYgdGhlIHZhbHVlIGRvZXMgbm90IG1hdGNoIHRoZSBzcGVjaWZpZWQgY29uZGl0aW9uLCB0aGFuIHRoZSBvdGhlciB2YWx1ZXMgd2lsbCBiZSB3aGF0IGV2ZXIgaXMgbGlzdGVkIGFmdGVyIGBUUlVFIH5gLiBXZSB3aWxsIHRoZW4gY3JlYXRlIHBvcHVsYXRpb24gY291bnRzIGFzIHdlIGRpZCBwcmV2aW91c2x5IGZvciB0aGUgb3RoZXIgZGVjYWRlcy4KCkZpbmFsbHksIHdlIHdpbGwgY3JlYXRlIG5ldyBzdW1zIGZvciB0aGUgc3VicG9wdWxhdGlvbnMgd2hlcmUgd2Ugc3VtIGFjcm9zcyB0aGUgdHdvIGBPdGhlcmAgc3ViZ3JvdXBzIGBSYWNlYCAgdG8gYSBjcmVhdGUgYSBzaW5nbGUgdmFsdWUgZm9yIGVhY2ggdmFsdWUgb2YgYFlFQVJgLCBgU0VYYCwgYEFHRV9HUk9VUGAsIGFuZCBgU1RBVEVgIGJ5IHVzaW5nIHRoZSBgZ3JvdXBfYnkoKWAgZnVuY3Rpb24gYW5kIGBzdW1tYXJpZSgpYC4gIAoKYGBge3J9CmRlbV85MF85OSAgJTw+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhzdGFydHNfd2l0aCgiV18iKSwKICAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQl8iKSwKICAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQUlBTl8iKSwKICAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQVBJXyIpKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiUkFDRSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJTVUJfUE9QX3RlbXAiKQoKZGVtXzkwXzk5ICU8PiUKICBtdXRhdGUoU0VYID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoUkFDRSwgIl9NIikgfiAiTWFsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkZlbWFsZSIpLAogICAgICAgICBSQUNFID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoUkFDRSwgIldfIikgfiAiV2hpdGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoUkFDRSwgIkJfIikgfiAiQmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiT3RoZXIiKSkgJT4lCiAgbGVmdF9qb2luKFNUQVRFX0ZJUFMsIGJ5ID0gIlNUQVRFRlAiKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1TVEFURUZQKQoKZGVtXzkwXzk5ICU8PiUKICBncm91cF9ieShZRUFSLCBTVEFURSwgQUdFX0dST1VQLCBTRVgsIFJBQ0UpICU+JQogIHN1bW1hcmlzZShTVUJfUE9QID0gc3VtKFNVQl9QT1BfdGVtcCksIC5ncm91cHM9ImRyb3AiKQoKYGBgCgpgYGB7cn0KcG9wXzkwXzk5IDwtIGRlbV85MF85OSAlPiUKICBncm91cF9ieShZRUFSLCBTVEFURSkgJT4lCiAgc3VtbWFyaXNlKFRPVF9QT1AgPSBzdW0oU1VCX1BPUCksIC5ncm91cHMgPSAiZHJvcCIpCgpkZW1fOTBfOTkgPC0gZGVtXzkwXzk5ICU+JQogIGxlZnRfam9pbihwb3BfOTBfOTksIGJ5PWMoIllFQVIiLCAiU1RBVEUiKSkgJT4lCiAgbXV0YXRlKFBFUkNfU1VCX1BPUCA9IChTVUJfUE9QL1RPVF9QT1ApKjEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCgtU1VCX1BPUCwgLVRPVF9QT1ApCgpkZW1fOTBfOTkKYGBgCgoKQWdhaW4sIHdlIHNob3VsZCBjaGVjayB0byBtYWtlIHN1cmUgdGhhdCB3ZSBoYXZlIHRoZSB0b3RhbCB2YWx1ZXMgd2Ugd291bGQgZXhwZWN0LiBXZSBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiB1bmlxdWUgdmFsdWVzIGZvciBlYWNoIG9mIG91ciB2YXJpYWJsZXMgYXMgaW4gd2l0aCB0aGUgZGF0YSBmcm9tIHRoZSA4MHMsIHNvIGlmIHdlIGNvbGxwYXNlZCB0aGUgZGF0YSBmb3IgdGhlIGRpZmZlcmVudCBhZGRpdGlvbmFsIHN1YnBvcHVsYXRpb25zIGluIHRoaXMgZGF0YSwgdGhlbiB3ZSBoYXZlIGRvbmUgaXQgY29ycmVjdGx5LiAKCkluZGVlZCBpdCBsb29rcyBsaWtlIHdlIGhhdmUgNTUsMDgwIHJvd3MsIHdoaWNoIGlzIHdoYXQgd2Ugd291bGQgZXhwZWN0IGFuZCBpcyB0aGUgc2FtZSBhcyB0aGUgbnVtYmVyIG9mIHJvd3Mgb2YgdGhlIGZpbmFsIGBkZW1fODBfODlgIGRhdGEuIExvb2tzIGdvb2QhCgo8Zm9udCBzaXplPSI2Ij4gKioyMDAwLTIwMTAqKjwvZm9udD4KCioqKgoKQWdhaW4sIGZvciB0aGlzIGRlY2FkZSB3ZSBuZWVkIHRvIGNvbWJpbmUgdGhlIGRhdGEgYWNyb3NzIHllYXJzLgoKYGBge3J9CmRlbV8wMF8xMCA8LSBkZW1fMDBfMTAgJT4lCiAgbWFwX2RmKGJpbmRfcm93cykKCmdsaW1wc2UoZGVtXzAwXzEwKQoKYGBgCgpPaywgdGhlIGRhdGEgbG9va3MgYSBiaXQgZGlmZmVyZW50IGZyb20gdGhlIG90aGVycy4gRmlyc3Qgd2Ugd2lsbCByZW1vdmUgYSBjb3VwbGUgb2YgdmFyaWFibGVzIHRoYXQgd2UgcHJvYmFibHkgZG9uJ3QgbmVlZC4gQWxzbyBpdCBsb29rcyBsaWtlIHdlIGhhdmUgc29tZSB2YWx1ZXMgZm9yIHRoZSBlbnRpcmUgVW5pdGVkIFNhdGVzIGFuZCB3ZSB3aWxsIGRyb3AgdGhlc2UgdG8gYmUgbGlrZSB0aGUgb3RoZXIgZGVjYWRlcy4KCgoKYGBge3J9CmRlbV8wMF8xMCAlPD4lCiAgc2VsZWN0KC1FU1RJTUFURVNCQVNFMjAwMCwtQ0VOU1VTMjAxMFBPUCkgJT4lCiAgZmlsdGVyKE5BTUUgIT0gIlVuaXRlZCBTdGF0ZXMiKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgbG90cyBvZiB2YWx1ZXMgdGhhdCBhcmUgemVyby4gQWNjb3JkaW5nIHRvIHRoZSBbdGVjaG5pY2FsIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvcG9wZXN0L3RlY2huaWNhbC1kb2N1bWVudGF0aW9uL2ZpbGUtbGF5b3V0cy8yMDAwLTIwMTAvaW50ZXJjZW5zYWwvc3RhdGUvc3QtZXN0MDBpbnQtYWxsZGF0YS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gZm9yIHRoaXMgZGF0YSwgemVybyB2YWx1ZXMgaW5kaWNhdGUgdGhlIHRvdGFsIGZvciB0aGUgb3RoZXIgY2F0ZWdvcmllcyBvZiBgU2V4YCwgYE9yaWdpbmAsIGBSYWNlYCwgYW5kIGBBR0VHUlBgLgoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI2MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidGVjaF9pbmZvLnBuZyIpKQpgYGAKClNvIHdlIHdpbGwgZHJvcCB0aGUgdG90YWwgdmFsdWVzIGZvciBgU0VYYCwgYFJBQ0VgLCBhbmQgYEFHRUdSUGAgYnkgcmVtb3ZpbmcgdGhlIHJvd3Mgd2hlcmUgdGhlc2UgdmFyaWFibGVzIGFyZSBlcXVhbCB0byB6ZXJvLgoKV2Ugd2lsbCBhbHNvIHdhbnQgdG8gb25seSBzZWxlY3QgZm9yIHRoZSB0b3RhbCB2YWx1ZXMgZm9yIGBPcmlnaW5gIGFzIHdlIGRvIG5vdCB3aXNoIHRvIGRpdmlkZSB0aGUgZGF0YSBpbnRvIHN1Ymdyb3VwcyBhYm91dCBoaXNwYW5pYyBldGhuaWNpdHkgYmVjYXVzZSB3ZSBkbyBub3QgaGF2ZSB0aGF0IGluZm9ybWF0aW9uIGZvciB0aGUgZmlyc3QgdHdvIGRlY2FkZXMuIFRodXMgd2Ugd2lsbCBmaWx0ZXIgZm9yIG9ubHkgdGhlIHJvd3Mgd2hlcmUgYE9yaWdpbmAgaXMgZXF1YWwgdG8gemVyby4KCldlIHdpbGwgYWxzbyB0aGVuIHJlbW92ZSB0aGUgYFJFR0lPTmAsIGBEaXZpc2lvbmAsIGBTVEFURWAsIGFuZCBgT3JpZ2luYCB2YXJpYWJsZXMuIFdlIHdpbGwgdGhlbiByZW5hbWUgYE5BTUVgIHRvIGJlIGBTVEFURWAgYW5kIHJlbmFtZSBgQUdFR1JQYCB0byBiZSBsaWtlIHRoZSBvdGhlciBkZWNhZGVzIGFzIGBBR0VfR1JPVVBgLgoKYGBge3J9CmRlbV8wMF8xMCAlPD4lCiAgZmlsdGVyKFNFWCAhPSAwLAogICAgICAgICBSQUNFICE9IDAsCiAgICAgICAgIEFHRUdSUCAhPSAwLCAKICAgICAgICAgT1JJR0lOID09IDApICU+JQogIGRwbHlyOjpzZWxlY3QoLVJFR0lPTiwgLURJVklTSU9OLCAtT1JJR0lOLCAtU1RBVEUpICU+JQogIHJlbmFtZSgiU1RBVEUiID0gTkFNRSwKICAgICAgICAgIkFHRV9HUk9VUCIgPSBBR0VHUlApCgpkZW1fMDBfMTAKYGBgCgoKTm93IHdlIG5lZWQgdG8gcmVjb2RlIHRoZSBudW1lcmljIHZhbHVlcyB0byB0aGUgdmFsdWVzIGluIHRoZSB0ZWNoaW5jYWwgZG9jdW1lbnRhdGlvbi4gV2UgY2FuIGRvIHNvIGJ5IGFkZGluZyBsYWJlbHMgdG8gZWFjaCBudW1lcmljIGxldmVsIHVzaW5nIHRoZSBiYXNlIGZ1bmN0aW9uIGBmYWN0b3IoKWAuCgpgYGB7cn0KZGVtXzAwXzEwICU8PiUKICBtdXRhdGUoU0VYID0gZmFjdG9yKFNFWCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IDE6MiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1hbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmVtYWxlIikpLAogICAgICAgICBSQUNFID0gZmFjdG9yKFJBQ0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAxOjYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJXaGl0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCbGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiT3RoZXIiLDQpKSksCiAgICAgICAgIEFHRV9HUk9VUCA9IGZhY3RvcihBR0VfR1JPVVAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAxOjE4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gcHVsbChkaXN0aW5jdChkZW1fNzdfNzksQUdFX0dST1VQKSwgQUdFX0dST1VQKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKZ2xpbXBzZShkZW1fMDBfMTApCmBgYAoKT0ssIHdlIGFsc28gd2FudCB0byBjaGFuZ2UgdGhlIHNoYXBlIG9mIHRoZSBkYXRhIHNvIHRoYXQgd2UgaGF2ZSBhIGBZRUFSYCB2YXJpYWJsZSBhbmQgZWFjaCBlc3RpbWF0ZSBvZiB0aGUgcG9wdWxhdGlvbiBpcyBhIHZhbHVlIGluIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCBgU1VCX1BPUF90ZW1wYC4gCgpgYGB7cn0KZGVtXzAwXzEwICU8PiUKICBwaXZvdF9sb25nZXIoY29scz1jb250YWlucygiRVNUSU1BVEUiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWUVBUiIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJTVUJfUE9QX3RlbXAiKQpgYGAKCldlIHdpbGwgbm93IGNsZWFuIHVwIHRoZSBgWUVBUmAgdmFyaWFibGUgdG8gb25seSBiZSB0aGUgbnVtZXJpYyB2YWx1ZSBieSBrZWVwaW5nIG9ubHkgdGhlIGxhc3QgNCB2YWx1ZXMgb2YgZWFjaCBzdHJpbmcgdXNpbmcgdGhlIGBzdHJfc3ViKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZS4KCmBgYHtyfQpkZW1fMDBfMTAgJTw+JQogIG11dGF0ZShZRUFSID0gc3RyX3N1YihZRUFSLCBzdGFydD0tNCkpICU+JQogIG11dGF0ZShZRUFSID0gYXMubnVtZXJpYyhZRUFSKSkKYGBgCgoKTm93IHdlIHdpbGwgY29sbGFwc2UgdGhlIGRhdGEgZm9yIHRoZSBkaWZmZXJlbnQgUkFDRVMgYW5kIGNhbGN1bGF0ZSBhIG5ldyBgU1VCX1BPUGAgdmFsdWUuIAoKYGBge3J9CmRlbV8wMF8xMCAlPD4lCiAgZ3JvdXBfYnkoWUVBUiwgQUdFX0dST1VQLCBTVEFURSwgU0VYLCBSQUNFKSAlPiUKICBzdW1tYXJpc2UoU1VCX1BPUCA9IHN1bShTVUJfUE9QX3RlbXApLCAuZ3JvdXBzID0gImRyb3AiKQpgYGAKCkFnaWFuLCB0aGUgZGltZW5zaW9ucyBsb29rIGFzIHdlIGV4cGVjdCB3aXRoIDYwLDU4OCByb3dzLiBUaGlzIHRpbWUgd2UgaGF2ZSB0d28gbGV2ZWxzIG9mIGBTRVhgLCB0aHJlZSBsZXZlbHMgb2YgYFJhY2VgLCAqKjExKiogbGV2ZWxzIG9mIGBZRUFSYCwgZWlnaHRlZW4gbGV2ZWxzIG9mIGBBR0VfR1JPVVBgLCBhbmQgZmlmdHkgb25lIGxldmVscyBvZiBgU1RBVEVgLiBJZiB3ZSBtdWx0aXBseSB0aGlzIHRvZ2V0aGVyIHdlIGdldCAxNiw1ODguIExvb2tzIGdvb2QhCgpOb3cgd2Ugd2lsbCBjYWxjdWxhdGUgdGhlIHRvdGFsIHBvbHV0YXRpb24gYW5kIHBlcmNlbnQgb2YgdGhlIHRvdGFsIGFzIHdlIGhhdmUgZG9uZSB3aXRoIHRoZSBwcmV2aW91cyBkZWNhZGVzLgoKCmBgYHtyfQpwb3BfMDBfMTAgPC0gZGVtXzAwXzEwICU+JQogIGdyb3VwX2J5KFlFQVIsIFNUQVRFKSAlPiUKICBzdW1tYXJpc2UoVE9UX1BPUCA9IHN1bShTVUJfUE9QKSwgLmdyb3VwcyA9ICJkcm9wIikKYGBgCgpXZSBjYW4gYWxzbyBjaGVjayB0aGF0IG91ciB3cmFuZ2xpbmcgd2FzIHBlcmZvcm1lY2QgY29ycmVjdGx5IGJ5IHN1bW1pbmcgdGhlIHZhbHVlcyBmb3IgdGhlIGluZGl2aWR1YWwgc3VicG9wdWxhdGlvbnMgcGVyY2VudGFnZXMgYW5kIHNlZWluZyBpZiBpdCB0b3RhbHMgdG8gMTAwLgoKYGBge3J9CmRlbV8wMF8xMCAlPiUKICBsZWZ0X2pvaW4ocG9wXzAwXzEwLCBieT1jKCJZRUFSIiwgIlNUQVRFIikpICU+JQogIGdyb3VwX2J5KFlFQVIsIFNUQVRFKSAlPiUKICBtdXRhdGUoUEVSQ19TVUJfUE9QID0gKFNVQl9QT1AvVE9UX1BPUCkqMTAwKSAlPiUKICBzdW1tYXJpc2UocGVyY190b3QgPSBzdW0oUEVSQ19TVUJfUE9QKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgbXV0YXRlKHBvc3NfZXJyb3IgPSBjYXNlX3doZW4oYWJzKHBlcmNfdG90IC0gMTAwKSA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBGQUxTRSkpICU+JQogIGdyb3VwX2J5KHBvc3NfZXJyb3IpICU+JQogIHRhbGx5KCkKCmBgYAoKTG9va3MgbGlrZSB0aGUgcGVyY2VudGFnZXMgZm9yIGVhY2ggc3RhdGUgZm9yIGVhY2ggeWVhciBhbGwgYWRkIHVwIHRvIDEwMCwgYXMgd2Ugd291bGQgZXhwZWN0LiBHcmVhdCEgTm93IHdlIHdpbGwgcmVhc2lnbiB0aGUgYGRlbV8wMF8xMGAgZGF0YSB3aXRoIHRoaXMgcHJvY2Vzc2luZy4gCgpgYGB7cn0KZGVtXzAwXzEwICU8PiUKICBsZWZ0X2pvaW4ocG9wXzAwXzEwLCBieSA9IGMoIllFQVIiLCAiU1RBVEUiKSkgJT4lCiAgbXV0YXRlKFBFUkNfU1VCX1BPUCA9IChTVUJfUE9QL1RPVF9QT1ApKjEwMCkgJT4lCiBzZWxlY3QoLVNVQl9QT1AsIC1UT1RfUE9QKQoKZGVtXzAwXzEwCmBgYAoKT0ssIG5vdyB3ZSBhcmUgcmVhZHkgdG8gY29tYmluZSBhbGwgb2Ygb3VyIGRlbWdyYXBoaWMgZGF0YSB0b2dldGhlciEKCjwvZGV0YWlscz4KCiMjIyBDb21iaW5pbmcgZGVtb2dyYXBoaWMgZGF0YQoKV2UgY2FuIGNoZWNrIHRoYXQgdGhlIGNvbG5hbWVzIGFyZSB0aGUgc2FtZSBmb3IgdGhlIGRhdGEgZm9yIGVhY2ggb2YgdGhlIGRlY2FkZXMgYnkgdXNpbmcgdGhlIGBzZXRlcXVhbCgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLgoKYGBge3J9CnNldGVxdWFsKGNvbG5hbWVzKGRlbV83N183OSksY29sbmFtZXMoZGVtXzgwXzg5KSkKc2V0ZXF1YWwoY29sbmFtZXMoZGVtXzgwXzg5KSxjb2xuYW1lcyhkZW1fOTBfOTkpKQpzZXRlcXVhbChjb2xuYW1lcyhkZW1fOTBfOTkpLGNvbG5hbWVzKGRlbV8wMF8xMCkpCmBgYAoKCldlIGNhbiBhbHNvIGNvbmZpcm0gdGhhdCB3ZSBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBhZ2UgZ3JvdXBzIGZvciBlYWNoIGRlY2FkZSBieSB1c2luZyB0aGUgYmFzZSBgbGVuZ3RoKClgIGZ1bmN0aW9uLiBJZiB5b3UgZGlkIG5vdCB0YWtlIGEgbG9vayBhdCB0aGUgd3JhbmdsaW5nIGZvciB0aGUgZGVtb2dyYXBoaWMgZGF0YSB0aGVuIHlvdSBtYXkgYmUgdW5mYW1pbGlhciB3aXRoIHRoZSBgcHVsbCgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBUaGlzIGFsbG93cyB5b3UgdG8gZ3JhYiB0aGUgdmFsdWVzIG9mIGEgdmFyaWFibGUgZnJvbSBhIHRpYmJsZS4gVGhlIGBkaXN0aW5jdCgpYCBmdW5jdGlvbiB3aGljaCBpcyBhbHNvIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgY3JlYXRlcyBhIHRpYmJsZSBvZiB0aGUgdW5pcXVlIHZhbHVlcyBmb3IgYSB2YXJpYWJsZS4KCmBgYHtyfQpsZW5ndGgocHVsbChkaXN0aW5jdChkZW1fNzdfNzksIEFHRV9HUk9VUCksIEFHRV9HUk9VUCkpCmxlbmd0aChwdWxsKGRpc3RpbmN0KGRlbV84MF84OSwgQUdFX0dST1VQKSwgQUdFX0dST1VQKSkKbGVuZ3RoKHB1bGwoZGlzdGluY3QoZGVtXzkwXzk5LCBBR0VfR1JPVVApLCBBR0VfR1JPVVApKQpsZW5ndGgocHVsbChkaXN0aW5jdChkZW1fMDBfMTAsIEFHRV9HUk9VUCksIEFHRV9HUk9VUCkpCmBgYAoKTG9va3MgZ29vZCEKCgpOb3cgd2Ugd2lsbCBjb21iaW5lIHRoZSBkYXRhIHVzaW5nIHRoZSBgYmluZF9yb3dzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFRoaXMgZnVuY3Rpb24gYXBwZW5kcyB0aGUgZGF0YSB0b2dldGhlciBiYXNlZCBvbiB0aGUgcHJlc2VuY2Ugb2YgY29sdW1ucyB3aXRoIHRoZSBzYW1lIG5hbWUgaW4gdGhlIGRpZmZlcmVudCB0aWJibGVzLgoKYGBge3J9CmRlbSA8LSBiaW5kX3Jvd3MoZGVtXzc3Xzc5LAogICAgICAgICAgICAgICAgIGRlbV84MF84OSwKICAgICAgICAgICAgICAgICBkZW1fOTBfOTksCiAgICAgICAgICAgICAgICAgZGVtXzAwXzEwKQpgYGAKCgpgYGB7cn0KZ2xpbXBzZShkZW0pCmBgYAoKR3JlYXQhIG5vdyB3ZSBoYXZlIGEgcmVhbGx5IGxhcmdlIHNpbmdsZSB0aWJibGUuCgpOb3cgd2Ugd2FudCB0byBzZWxlY3Qgc2ltaWxhciBkZW1vZ3JhcGhpYyBkYXRhIHRvIHdoYXQgd2FzIHVzZWQgaW4gdGhlIHByZXZpb3VzIGFuYWx5c2VzLgoKSGVyZSBpcyB0aGUgdGFibGUgZnJvbSB0aGUgW0Rvbm9odWUgcGFwZXJdKGh0dHBzOi8vd3d3Lm5iZXIub3JnL3BhcGVycy93MjM1MTAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHRoYXQgY29tcGFyZXMgdGhlIGRhdGEgdXNlZCBpbiB0aGUgYW5hbHlzZXMuCgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC5oZWlnaHQgPSAnMTAwJScsIG91dC53aWR0aCA9ICcxMDAlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCJpbWciLCdEb25vaHVlX1RhYmxlMi5wbmcnKSkKYGBgCldlIGNhbiBzZWUgdGhhdCBvbmx5IHRoZSBwZXJjZW50YWdlIG9mIG1hbGVzIHRoYXQgd2VyZSBmcm9tIGFnZSAxNS0zOSBvZiB0aGUgcmFjZSBncm91cHMgKGJsYWNrLCB3aGl0ZSwgYW5kIG90aGVyKSB3ZXJlIHVzZWQgaW4gdGhlIERvbm9odWUgYW5hbHlzaXMuCgpVbHRpbWF0ZWx5IHdlIGludGVuZCB0byBtYWtlIGEgdGliYmxlIG9mIGRhdGEgdGhhdCBpcyBzaW1pbGFyIHRvIGVhY2ggYW5hbHlzaXMuIFRoZXJlZm9yZSwgd2Ugd2lsbCBjcmVhdGUgYSBkYXRhIHRpYmJsZSBhYm91dCB0aGUgZGVtb2dycGhhaWMgZGF0YSBmb3IgZWFjaCBhbmFseXNpcyBub3cuCgpUbyBkbyBzbyB3ZSB3aWxsIGZpcnN0IGNyZWF0ZSBhIHZlY3RvciBvZiB0aGUgYWdlIGdyb3VwcyB0aGF0IHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUgRG9ub2h1ZS1saWtlIGFuYWx5c2lzLCB0aGF0IHdlIHdpbGwgY2FsbCBgRE9OT0hVRV9BR0VfR1JPVVBTYC4gV2Ugd2lsbCB0aGVuIGZpbHRlciBmb3Igb25seSB0aGUgYWdlIGdyb3VwcyBpbiB0aGlzIHZlY3RvciBieSB1c2luZyB0aGUgYGZpbHRlcigpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIGFuZCB0aGUgYCVpbiVgIG9wZXJhdG9yIHRvIGluZGljYXRlIHRoYXQgd2Ugd2FudCB0byBrZWVwIGFsbCBgQUdFX0dST1VQYCB2YWx1ZXMgdGhhdCBhcmUgZXF1YWwgdG8gdGhvc2Ugd2l0aGluIGBET05PSFVFX0FHRV9HUk9VUFNgLiBXZSBhbHNvIHdhbnQgdG8gZmlsdGVyIGZvciBvbmx5IHBvcHVsYXRpb24gcGVyY2VudGFnZXMgZm9yIG1hbGVzIGJ5IHVzaW5nIHRoZSBgPT1gIG9wZXJhdG9yLiBUaGVuIHdlIGNhbiBjb2xscGFzZSB0aGUgYWdlIGdyb3VwcyBmcm9tIDIwLTM5IGJ5IHVzaW5nIHRoZSBgZmN0X2NvbGxwYXNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZm9yY2F0c2AgcGFja2FnZS4KCmBgYHtyfQpET05PSFVFX0FHRV9HUk9VUFMgPC0gYygiMTUgdG8gMTkgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAiMjAgdG8gMjQgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAiMjUgdG8gMjkgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAiMzAgdG8gMzQgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAiMzUgdG8gMzkgeWVhcnMiKQoKZGVtX0RPTk9IVUUgPC0gZGVtICU+JQogIGZpbHRlcihBR0VfR1JPVVAgJWluJSBET05PSFVFX0FHRV9HUk9VUFMsCiAgICAgICAgICAgICAgIFNFWCA9PSAiTWFsZSIpICU+JQogIG11dGF0ZShBR0VfR1JPVVAgPSBmY3RfY29sbGFwc2UoQUdFX0dST1VQLCAiMjAgdG8gMzkgeWVhcnMiPWMoIjIwIHRvIDI0IHllYXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyNSB0byAyOSB5ZWFycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMzAgdG8gMzQgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjM1IHRvIDM5IHllYXJzIikpKQoKZGVtX0RPTk9IVUUKYGBgCgpXZSBhbHNvIHdhbnQgdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHRoYXQgd2lsbCBjb250YWluIGFsbCB0aGUgZGVtb2dyYXBoaWMgaW5mb3JtYXRpb24gZm9yIGVhY2ggcGVyY2VudGFnZSBqdXN0IGFzIHdhcyBkb25lIGluIHRoZSBbRG9ub2h1ZSwgZXQgYWwuXShodHRwczovL3d3dy5uYmVyLm9yZy9wYXBlcnMvdzIzNTEwLnBkZil7dGFyZ2V0PSJfYmxhbmsifSBhbmFseXNpcy4gVGhpcyBzaG91bGQgcmVzdWx0IGluIDYgZGlmZmVyZW50IGRlbW9ncmFwaGljIHZhcmlhYmxlcy4KClRvIGRvIHRoaXMgd2Ugd2lsbCBtb2RpZnkgdGhlIGBBR0VfR1JPVVBgIHZhcmlhYmxlIGJ5IHVzaW5nIHRoZSBgbXV0YXRlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFdlIHdpbGwgcmVwbGFjZSB0aGUgc3BhY2VzIGluIHRoZSBub3cgdHdvIGFnZSBncm91cCBjYXRlZ29yaXNlIHdpdGggYW5kIHVuZGVzcnNjb3JlIHVzaW5nIHRoZSBgc3RyX3JlcGxhY2VfYWxsKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZSB3aGljaCByZXBsYWNlcyBhbGwgaW5zdGFuY2VzIG9mIGEgcGF0dGVybiBpbiBhIGNoYXJhY3RlciBzdHJpbmcuIAoKVGhlbiB3ZSB3aWxsIHVzZSB0aGUgYGdyb3VwX2J5KClgIGZ1bmN0aW9uIGFuZCB0aGUgYHN1bW1hcmlzZSgpYCBmdW50aW9uIGFsc28gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBhbGxvdyB1cyB0byBjYWxjdWxhdGUgYSBzdW0gb2YgdGhlIHBlcmNlbnRhZ2VzIGZvciBlYWNoIG9mIHRoZSBzdWJwb3B1bGF0aW9uIHBlcmNlbnRhZ2VzIGZvciB0aGUgbmV3bHkgbW9kaWZlZCBhZ2UgZ3JvdXBzIGluIGBBR0VfR1JPVVBgLiBUaGUgYC5ncm91cHMgPSAiZHJvcCJgIGFyZ3VtZW50IGFsbG93cyBmb3IgdGhlIGdyb3VwaW5nIHRvIGJlIHJlbW92ZWQgYWZ0ZXIgdGhlIGBzdW1tYXJpc2UoKWAgZnVuY3Rpb24uCgpgYGB7cn0KZGVtX0RPTk9IVUUgJTw+JQogIG11dGF0ZShBR0VfR1JPVVAgPSBzdHJfcmVwbGFjZV9hbGwoc3RyaW5nID0gQUdFX0dST1VQLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiICIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiXyIpKSAlPiUKICBncm91cF9ieShZRUFSLCBTVEFURSwgUkFDRSwgU0VYLCBBR0VfR1JPVVApICU+JQogIHN1bW1hcmlzZShQRVJDX1NVQl9QT1AgPSBzdW0oUEVSQ19TVUJfUE9QKSwgLmdyb3VwcyA9ICJkcm9wIikKCmRlbV9ET05PSFVFCmBgYAoKTm93IHdlIHdpbGwgY29tYmluZSB0aGUgdmFyaWFibGVzIGBSQUNFYCwgYFNFWGAsIGFuZCBgQUdFX0dST1VQYCB0b2dldGhlciBpbnRvIG9uZSBzdHJpbmcgc2VwYXJhdGVkIGJ5IHVuZGVyc2NvcmVzIHVzaW5nIHRoZSBgdW5pdGVgIGZ1bmN0aW9uIG9mIHRoZSBgdGlkeXJgIHBhY2thZ2UuIHdlIHdpbGwgY2FsbCB0aGlzIG5ldyB2YXJpYWJsZSBgVkFSSUFCTEVgLgpXZSB3aWxsIHJlbmFtZSB0aGUgYFBFUkNfU1VCX1BPUGAgdmFyaWFibGUgdG8gYmUgYFZBTFVFYCB1c2luZyB0aGUgYHJlbmFtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBUaGUgbmV3IG5hbWUgc2hvdWxkIGJlIGxpc3RlZCBmaXJzdCBiZWZvcmUgdGhlIGA9YC4KCmBgYHtyfQpkZW1fRE9OT0hVRSAlPD4lCiAgdW5pdGUoY29sID0gIlZBUklBQkxFIiwgUkFDRSwgU0VYLCBBR0VfR1JPVVAsIHNlcCA9ICJfIikgJT4lCiAgcmVuYW1lKCJWQUxVRSIgPSBQRVJDX1NVQl9QT1ApCgpkZW1fRE9OT0hVRQpgYGAKCkxldCdzIGRvIGEgcXVpY2sgcm93IG51bWJlciBjaGVjay4gV2UgaGF2ZSBzaXggZGlmZmVyZW50IGRlbW9ncmFwaGljIHZhcmlhYmxlcywgNTEgc3RhdGVzIChEQyBjb3VudHMgYXMgYSBzdGF0ZSBpbiB0aGlzIGNhc2UpLCBhbmQgMzQgZGlmZmVyZW50IHllYXJzIGZyb20gMTk3NyB0byAyMDEwLCB3ZSBzaG91bGQgaGF2ZSAxMCw0MDQgcm93cywgd2hpY2ggd2UgZG8hCgpOb3csIGxldCdzIGRvIHRoZSBzYW1lIGZvciB0aGUgIkxvdHQtbGlrZSIgYW5hbHlzaXMuCgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC5oZWlnaHQgPSAnMTAwJScsIG91dC53aWR0aCA9ICcxMDAlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlKCJpbWciLCdEb25vaHVlX1RhYmxlMi5wbmcnKSkKYGBgCgpTbywgaW4gdGhpcyBhbmFseXNpcyB0aGVyZSB3ZXJlIDM2IHZhcmlhYmxlcyBjb3ZlcmluZyBwZXJjZW50YWdlcyBvZiBpbmRpdml1YWxzIGZyb20gMTAgdG8gb3ZlciA2NSwgdGhyZWUgIHJhY2UgZ3JvdXBzIGFuZCBib3RoIG1hbGVzIGFuZCBmZW1hbGVzLiBUaGlzIHRhYmxlIGlzIG1pc3ByaW50ZWQgYW5kIGRvZXMgbm90IGluY2x1ZGUgdGhlIHdvcmQgIk90aGVyIiBmb3IgdGhlIHRoaXJkIHJhY2UgZ3JvdXAgdGhhdCB3YXMgdXNlZC4gCgpGaXJzdCB3ZSB3aWxsIGZpbHRlciBvdXQgdGhlIGFnZSBncm91cHMgdGhhdCB3ZXJlIG5vdCBpbmNsdWRlZC4gVGhlbiB3ZSB3aWxsIGNvbGxhcHNlIHRoZSBhZ2UgZ3JvdXBzIHRvIHRob3NlIHRoYXQgd2VyZSB1c2VkIGJ5IExvdHQgZXQgYWwuIGFnYWluIHVzaW5nIHRoZSBgZmN0X2NvbGxwYXNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZm9yY2F0c2AgcGFja2FnZS4gCgpBbHNvIHdlIHdpbGwgYWdhaW4gY29tYmluZSB0aGUgdmFsdWVzIGFjcm9zcyB0aGUgdmFyaWFibGVzIHRvIGNyZWF0ZSBhIG5ldyBkZW1vZ3JhcGhpYyB2YXJhaWJsZSB3aXRoIDM2IGxldmVscy4gCgpgYGB7cn0KTE9UVF9BR0VfR1JPVVBTX05VTEwgPC0gYygiVW5kZXIgNSB5ZWFycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIjUgdG8gOSB5ZWFycyIpCgpkZW1fTE9UVCA8LSBkZW0gJT4lCiAgZmlsdGVyKCEoQUdFX0dST1VQICVpbiUgTE9UVF9BR0VfR1JPVVBTX05VTEwpICklPiUKICBtdXRhdGUoQUdFX0dST1VQID0gZmN0X2NvbGxhcHNlKEFHRV9HUk9VUCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxMCB0byAxOSB5ZWFycyI9YygiMTAgdG8gMTQgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxNSB0byAxOSB5ZWFycyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwIHRvIDI5IHllYXJzIj1jKCIyMCB0byAyNCB5ZWFycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjI1IHRvIDI5IHllYXJzIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMzAgdG8gMzkgeWVhcnMiPWMoIjMwIHRvIDM0IHllYXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMzUgdG8gMzkgeWVhcnMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI0MCB0byA0OSB5ZWFycyI9YygiNDAgdG8gNDQgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI0NSB0byA0OSB5ZWFycyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjUwIHRvIDY0IHllYXJzIj1jKCI1MCB0byA1NCB5ZWFycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjU1IHRvIDU5IHllYXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNjAgdG8gNjQgeWVhcnMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI2NSB5ZWFycyBhbmQgb3ZlciI9YygiNjUgdG8gNjkgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI3MCB0byA3NCB5ZWFycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjc1IHRvIDc5IHllYXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODAgdG8gODQgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NSB5ZWFycyBhbmQgb3ZlciIpKSkgJT4lCiAgbXV0YXRlKEFHRV9HUk9VUCA9IHN0cl9yZXBsYWNlX2FsbChBR0VfR1JPVVAsIiAiLCJfIikpICU+JQogIGdyb3VwX2J5KFlFQVIsIFNUQVRFLCBSQUNFLCBTRVgsIEFHRV9HUk9VUCkgJT4lCiAgc3VtbWFyaXNlKFBFUkNfU1VCX1BPUCA9IHN1bShQRVJDX1NVQl9QT1ApLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICB1bml0ZShjb2wgPSAiVkFSSUFCTEUiLCBSQUNFLCBTRVgsIEFHRV9HUk9VUCwgc2VwID0gIl8iKSAlPiUKICByZW5hbWUoIlZBTFVFIj1QRVJDX1NVQl9QT1ApCmBgYAoKV2UgY2FuIGluZGVlZCBjaGVjayB0aGF0IHdlIGhhdmUgdGhlIGNvcnJlY3QgbnVtYmVyIG9mIGxldmVscyBmb3IgYFZBUklBQkxFYCB1c2luZyB0aGUgYGRpc3RpbmN0KClgIGZ1bmN0aW9uLgoKYGBge3J9CiBkaXN0aW5jdChkZW1fTE9UVCwgVkFSSUFCTEUpCmBgYAogIAojIyBDb21iaW5pbmcgcG9wdWxhdGlvbiBEYXRhCgpXZSBhbHNvIGhhdmUgcG9wdWxhdGlvbiBkYXRhIGZvciBlYWNoIGRlY2FkZSB0aGF0IGNhbWUgZnJvbSAgd3JhbmdsaW5nIG9mIHRoZSBkZW1vZ3JwaGljIGRhdGEuCgpXZSBhZ2FpbiB3YW50IHRvIGNvbWJpbmUgdGhpcyBkYXRhLCBzbyBsZXQncyBhZ2FpbiBtYWtlIHN1cmUgdGhhdCBhbGwgdGhlIGRpZmZlcmVudCB0aWJibGVzIGhhdmUgdGhlIHNhbWUgY29sdW1uIG5hbWVzLgoKYGBge3J9CnNldGVxdWFsKGNvbG5hbWVzKHBvcF83N183OSksY29sbmFtZXMocG9wXzgwXzg5KSkKc2V0ZXF1YWwoY29sbmFtZXMocG9wXzgwXzg5KSxjb2xuYW1lcyhwb3BfOTBfOTkpKQpzZXRlcXVhbChjb2xuYW1lcyhwb3BfOTBfOTkpLGNvbG5hbWVzKHBvcF8wMF8xMCkpCgpoZWFkKHBvcF83N183OSkKaGVhZChwb3BfODBfODkpCmhlYWQocG9wXzkwXzk5KQpoZWFkKHBvcF8wMF8xMCkKYGBgCgpMb29rcyBnb29kIQoKYGBge3J9CnBvcHVsYXRpb25fZGF0YSA8LSBiaW5kX3Jvd3MocG9wXzc3Xzc5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcF84MF84OSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3BfOTBfOTksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wXzAwXzEwKQoKcG9wdWxhdGlvbl9kYXRhIDwtIHBvcHVsYXRpb25fZGF0YSAlPiUKICBtdXRhdGUoVkFSSUFCTEUgPSAiUG9wdWxhdGlvbiIpICU+JQogIHJlbmFtZSgiVkFMVUUiPVRPVF9QT1ApCmBgYAoKV2UgY291bGQgY2hlY2sgdGhhdCB3ZSBoYXZlIDUxIHZhbHVlcyBmb3IgZWFjaCB5ZWFyIGJ5IHVzaW5nIHRoZSBgY291bnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4KCmBgYHtyfQpwb3B1bGF0aW9uX2RhdGEgJT4lCiAgY291bnQoWUVBUikKYGBgCgojIyBQb2xpY2Ugc3RhZmZpbmcKCjxkZXRpYWxzPiA8c3VtbWFyeT4gY2xpY2sgaGVyZSB0byBzZWUgZGV0aWFscyBhYm91dCBob3cgdGhlIHBsaWNlIHN0YWZmaW5nIGRhdGEgd2FzIHdyYW5nbGVkLiA8L3N1bW1hcnk+CgpPSywgbm93IHdlIHdpbGwgd3JhbmdsZSB0aGUgcG9saWNlIHN0YWZmaW5nIGRhdGEuIFdlIHdhbnQgdG8gbGltaXQgdGhlIGRhdGEgdG8gb25seSB0aGUgeWVhcnMgb2YgaW50ZXJlc3QuIFRoZW4gd2Ugd2lsbCBhbHNvIHJlcGxhY2UgTkEgdmFsdWVzIHdpdGggemVybyBmb3IgdGhlIGBtYWxlX3RvdGFsX2N0YCBhbmQgYGZlbWFsZV90b3RhbF9jdGAgdmFyaWFibGVzIHVzaW5nIHRoZSBgcmVwbGFjZV9uYSgpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrZ2UuIFdlIHdpbGwgYWxzbywgdXNlIHRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gc2VsZWN0IGFuZCBtdXRhdGUgYm90aCBvZiB0aGVzZSBjb2x1bW5zIGluIHRoaXMgd2F5LiBTaW5jZSBib3RoIG9mIHRoZXNlIHZhcmlhYmxlcyBoYXZlIGB0b3RhbF9jdGAgaW4gdGhlIG5hbWUgYW5kIG5vIG90aGVyIHZhcmlhYmxlcyBkbywgd2UgY2FuIHVzZSB0aGUgYGNvbnRhaW5zKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gc3BlY2lmeSB0aGF0IHdlIHdhbnQgdG8gdXNlIHRoZXNlIGNvbHVtbnMgaW5zdGVhZCBvZiBsaXN0aW5nIGJvdGggb3V0LgoKYXZvY2Fkby4uLiB3aHkgbm90IDIwMTAuLi4uCgpgYGB7cn0KZ2xpbXBzZShwc19kYXRhKQoKcHNfZGF0YSAlPD4lCiAgZmlsdGVyKGRhdGFfeWVhciA+PSAxOTc3LCAKICAgICAgICAgZGF0YV95ZWFyIDw9IDIwMTQpICU+JQptdXRhdGUoYWNyb3NzKC5jb2xzID1jb250YWlucygidG90YWxfY3QiKSwgfnJlcGxhY2VfbmEoLiwgMCkpKQoKZ2xpbXBzZShwc19kYXRhKQpgYGAKCk5vdyB3ZSBjYW4gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCBgb2ZmaWNlcl90b3RhbCB0aGF0IGlzIHRoZSBzdW0gb2YgdGhlc2UgdmFyaWFibGVzYC4gV2Ugd2lsbCB0aGVuIGtlZXAganVzdCB0aGlzIHZhcmlhYmxlIGFzIHdlbGwgYXMgdGhlIGBkYXRhX3llYXJgLCBgcHViX2FnZW5jeV9uYW1lYCwgYW5kIGBzdGF0ZV9hYmJyYC4KCmBgYHtyfQoKcHNfZGF0YSAlPD4lCiAgbXV0YXRlKG9mZmljZXJfdG90YWwgPSBtYWxlX3RvdGFsX2N0ICsgZmVtYWxlX3RvdGFsX2N0KSAlPiUKICBkcGx5cjo6c2VsZWN0KGRhdGFfeWVhciwKICAgICAgICAgICAgICAgIHB1Yl9hZ2VuY3lfbmFtZSwKICAgICAgICAgICAgICAgIHN0YXRlX2FiYnIsCiAgICAgICAgICAgICAgICBvZmZpY2VyX3RvdGFsKQoKcHNfZGF0YQpgYGAKCk5vdyB3ZSBhbHNvIHdhbnQgdG8gZ2V0IGNvbGxhcHNlIGJ5IGBwdWJfYWdlbmN5X25hbWVgIHRvIGdldCBhIHRvdGFsIGNvdW50IGZvciBlYWNoIHllYXIgYW5kIGVhY2ggc3RhdGUuIFNvIHdlIHdpbGwgZG8gdGhpcyBieSB1c2luZyB0aGUgYGdyb3VwX2J5KClgIGZ1bmN0aW9uIGFuZCBncm91cGluZyBieSBgZGF0YV95ZWFyYCBhbmQgYHN0YXRlX2FiYnJgIGFuZCB1c2luZyB0aGUgYHN1bW1hcmlzZSgpYCBmdW5jdGlvbiB0byBjYWxjdWxhdGUgYSBzdW0uCgpgYGB7cn0KcHNfZGF0YSAlPD4lCiAgZ3JvdXBfYnkoZGF0YV95ZWFyLCBzdGF0ZV9hYmJyKSAlPiUKICBzdW1tYXJpc2Uob2ZmaWNlcl9zdGF0ZV90b3RhbD1zdW0ob2ZmaWNlcl90b3RhbCksIC5ncm91cHMgPSAiZHJvcCIpCgpwc19kYXRhCmBgYApBbmQgd2Ugd2lsbCBjaGVjayB0aGF0IHdlIGhhdmUgc2FtZSBudW1iZXIgb2YgdmFsdWVzICh0aGUgbnVtYmVyIG9mIHllYXJzIGluY2x1ZGVkIGluIHRoZSBkYXRhKSBmb3IgZWFjaCBzdGF0ZS4KCmBgYHtyfQpwc19kYXRhICU+JQogIGNvdW50KHN0YXRlX2FiYnIpIApgYGAKV2Ugd2lsbCByZW1vdmUgYSBmZXcgc3RhdGVzIG5vdy4KQVZvY2Fkby0gd2h5PwpOQiBpcyAgTmVicmFza2EuIFRoaXMgd2FzIGNoYW5nZWQgdG8gTkUgdG8gYXZvaWQgY29uZnVzaW9ucyB3aXRoIE5CIGluIENhbmFkYS4gVGhpcyBkYXRhc2V0IHVzZXMgTkIKCmBgYHtyfQoKc3RhdGVfb2ZfaW50ZXJlc3RfTlVMTCA8LSBjKCJBUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR00iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNaIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTVAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9UIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQUiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVkkiKQoKc3RhdGVfYWJiX2RmIDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQoc3RhdGUuYWJiLCBzdGF0ZS5uYW1lKSkKCmNvbG5hbWVzKHN0YXRlX2FiYl9kZikgPC0gYygic3RhdGVfYWJiciIsICJTVEFURSIpCgpwcmludChzdGF0ZV9hYmJfZGYpCgpzdGF0ZV9hYmJfZGYgPC0gc3RhdGVfYWJiX2RmICU+JQogIGFkZF9yb3coc3RhdGVfYWJicj0iREMiLAogICAgICAgICAgU1RBVEU9IkRpc3RyaWN0IG9mIENvbHVtYmlhIikKCmRlbm9taW5hdG9yX3RlbXAgPC0gcG9wdWxhdGlvbl9kYXRhICU+JQogIGRwbHlyOjpzZWxlY3QoLVZBUklBQkxFKSAlPiUKICByZW5hbWUoIlBvcHVsYXRpb25fdGVtcCI9VkFMVUUpCgpwc19kYXRhIDwtIHBzX2RhdGEgJT4lCiAgZmlsdGVyKCEoc3RhdGVfYWJiciAlaW4lIHN0YXRlX29mX2ludGVyZXN0X05VTEwpKSAlPiUKICBtdXRhdGUoc3RhdGVfYWJiciA9IGNhc2Vfd2hlbihzdGF0ZV9hYmJyID09ICJOQiIgfiAiTkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBzdGF0ZV9hYmJyKSkgJT4lCiAgbGVmdF9qb2luKHN0YXRlX2FiYl9kZiwgYnkgPSAic3RhdGVfYWJiciIpICU+JQogIGRwbHlyOjpzZWxlY3QoLXN0YXRlX2FiYnIpICU+JQogIHJlbmFtZShZRUFSID0gImRhdGFfeWVhciIsCiAgICAgICAgIFZBTFVFID0gIm9mZmljZXJfc3RhdGVfdG90YWwiKSAlPiUKICBtdXRhdGUoVkFSSUFCTEUgPSAib2ZmaWNlcl9zdGF0ZV90b3RhbCIpICU+JQogIGxlZnRfam9pbihkZW5vbWluYXRvcl90ZW1wLCBieT1jKCJTVEFURSIsIllFQVIiKSkgJT4lCiAgbXV0YXRlKFZBTFVFID0gKFZBTFVFKjEwMDAwMCkgLyBQb3B1bGF0aW9uX3RlbXApICU+JQogIG11dGF0ZShWQUxVRSA9IGxhZyhWQUxVRSkpICU+JQogIG11dGF0ZShWQVJJQUJMRSA9ICJwb2xpY2VfcGVyXzEwMGtfbGFnIikgJT4lCiAgZHBseXI6OnNlbGVjdCgtUG9wdWxhdGlvbl90ZW1wKQpgYGAKPC9kZXRhaWxzPgoKCiMjIFVuZW1wbG95bWVudAoKVGhlIGZpcnN0IHRoaW5nIHdlIG5lZWQgdG8gZG8gd2l0aCB0aGUgdW5lbXBsb3ltZW50IGRhdGEgaXMgY29tYmluZSB0aGUgZGF0YSBhY3Jvc3MgdGhlIGRpZmZlcmVudCBzdGF0ZXMuCiBXZSBjYW4gZG8gdGhhdCB1c2luZyB0aGUgYGJpbmRfcm93cygpYCBmdW5jdGlvbiBvZiBgZHBseXJgIHdoaWNoIGFwcGVuZHMgdGhlIGRhdGEgdG9nZXRoZXIgYmFzZWQgb24gdGhlIHByZXNlbmNlIG9mIGNvbHVtbnMgd2l0aCB0aGUgc2FtZSBuYW1lIGluIHRoZSBkaWZmZXJlbnQgdGliYmxlcy4gV2Ugd2lsbCB1c2UgdGhlIGBtYXBfZGYoKWAgZnVuY3Rpb24gb2YgdGhlIGBwdXJycmAgcGFja2FnZSB0byBhbGxvdyB1cyB0byBkbyB0aGlzIGFjcm9zcyBlYWNoIHRpYmJsZSBpbiBvdXIgbGlzdC4gV2Ugd2lsbCB0aGVuIHNlbGVjdCBqdXN0IHRoZSBhbm51YWwgZGF0YSBmb3IgZWFjaCBzdGF0ZSBhbmQgd2Ugd2lsbCByZW5hbWUgb3VyIHZhcmlhYmxlcyB0byBiZSBjb25zaXN0ZW50IHdpdGggc29tZSBvZiBvdGhlciBkYXRhLgogCmBgYHtyfQoKdWVfcmF0ZV9kYXRhIDwtIHVlX3JhdGVfZGF0YSAlPiUKICBtYXBfZGYoYmluZF9yb3dzLCAuaWQgPSAiU1RBVEUiKQoKaGVhZCh1ZV9yYXRlX2RhdGEpCgp1ZV9yYXRlX2RhdGEgPC0gdWVfcmF0ZV9kYXRhICU+JQogIyBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpICU+JQogIGRwbHlyOjpzZWxlY3QoU1RBVEUsIFllYXIsIEFubnVhbCkgJT4lCiAgcmVuYW1lKCJZRUFSIj0gWWVhciwKICAgICAgICAgIlZBTFVFIiA9IEFubnVhbCkgJT4lCiAgbXV0YXRlKFZBUklBQkxFID0gIlVuZW1wbG95bWVudF9yYXRlIikKYGBgCgojIyBQb3ZlcnR5IHJhdGUKCgpgYGB7cn0KaGVhZChwb3ZlcnR5X3JhdGVfZGF0YSkKCmNvbG5hbWVzKHBvdmVydHlfcmF0ZV9kYXRhKSA8LSBjKCJTVEFURSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUb3RhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOdW1iZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTnVtYmVyX3NlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBlcmNlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUGVyY2VudF9zZSIpCgp0YWlsKHBvdmVydHlfcmF0ZV9kYXRhKQoKbm90ZXMgPC0gNAoKcG92ZXJ0eV9yYXRlX2RhdGEgPC0gcG92ZXJ0eV9yYXRlX2RhdGFbLSgoZGltKHBvdmVydHlfcmF0ZV9kYXRhKVsxXS1ub3RlcysxKTpkaW0ocG92ZXJ0eV9yYXRlX2RhdGEpWzFdKSxdCgpzdGF0ZXNfZXEgPC0gNTEKCmV4dHJhX2NvbCA8LSAyCgpyZXBfcm93cyA8LSBzdGF0ZXNfZXEgKyBleHRyYV9jb2wKCmdyb3VwcyA8LSAoZGltKHBvdmVydHlfcmF0ZV9kYXRhKVsxXSkvKHJlcF9yb3dzKQoKcGFzdGUoZ3JvdXBzIC0gKDIwMTgtMTk4MCArIDEpLCAiZXh0cmEgZ3JvdXBzIikKCnBvdmVydHlfcmF0ZV9kYXRhJHllYXJfZ3JvdXAgPC0gcmVwKDE6Z3JvdXBzLCBlYWNoPXJlcF9yb3dzKQoKcG92ZXJ0eV9yYXRlX2RhdGEgPC0gcG92ZXJ0eV9yYXRlX2RhdGEgJT4lCiAgZ3JvdXBfYnkoeWVhcl9ncm91cCkgJT4lCiAgZ3JvdXBfc3BsaXQoKQoKaGVhZChwb3ZlcnR5X3JhdGVfZGF0YVtbMV1dKQoKcG92ZXJ0eV9yYXRlX2RhdGEgPC0gcG92ZXJ0eV9yYXRlX2RhdGEgJT4lCiAgbWFwKH5tdXRhdGUoLiwKICAgICAgICAgICAgICByb3dfaWQgPSByb3dfbnVtYmVyKCkpKSAlPiUKICBtYXAofmZpbHRlciguLHJvd19pZCAhPSAyKSkgJT4lCiAgbWFwKH5kcGx5cjo6c2VsZWN0KC4sLXJvd19pZCkpCgpwb3ZlcnR5X3JhdGVfZGF0YV9uYW1lcyA8LSBwb3ZlcnR5X3JhdGVfZGF0YSAlPiUKICBzYXBwbHkoLiwgIlsiLDEsMSwgZHJvcD1UUlVFKSAlPiUKICBzdHJfcmVwbGFjZV9hbGwoLiwiWzpzcGFjZTpdIiwiXyIpCgpuYW1lcyhwb3ZlcnR5X3JhdGVfZGF0YSkgPC0gcG92ZXJ0eV9yYXRlX2RhdGFfbmFtZXMKCiMgUmVjYWxsIDIgZXh0cmEgZ3JvdXBzLiAKIyBmb290bm90ZXMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvdG9waWNzL2luY29tZS1wb3ZlcnR5L3BvdmVydHkvZ3VpZGFuY2UvcG92ZXJ0eS1mb290bm90ZXMvY3BzLWhpc3RvcmljLWZvb3Rub3Rlcy5odG1sCgpwb3ZlcnR5X3JhdGVfZGF0YSRgMjAxN18oMjEpYCA8LSBOVUxMCgpwb3ZlcnR5X3JhdGVfZGF0YSRgMjAxM18oMTkpYCA8LSBOVUxMCgpwb3ZlcnR5X3JhdGVfZGF0YV9uYW1lcyA8LSBwb3ZlcnR5X3JhdGVfZGF0YSAlPiUKICBzYXBwbHkoLiwgIlsiLDEsMSwgZHJvcD1UUlVFKSAlPiUKICBzdHJfc3ViKC4sIHN0YXJ0ID0gMSwgZW5kPTQpCgpuYW1lcyhwb3ZlcnR5X3JhdGVfZGF0YSkgPC0gcG92ZXJ0eV9yYXRlX2RhdGFfbmFtZXMKCnBvdmVydHlfcmF0ZV9kYXRhIDwtIHBvdmVydHlfcmF0ZV9kYXRhICU+JQogIG1hcF9kZihiaW5kX3Jvd3MsIC5pZCA9ICJZRUFSIikgJT4lCiAgZHBseXI6OnNlbGVjdCgteWVhcl9ncm91cCkKCnBvdmVydHlfcmF0ZV9kYXRhIDwtIHBvdmVydHlfcmF0ZV9kYXRhICU+JQogICAgbXV0YXRlKG5fbmEgPSByb3dTdW1zKGlzLm5hKC4pKSkgCgojIFRoaXMgc2hvd3MgdGhhdCB0aGVyZSBpcyBzeXN0ZW1hdGljIG1pc3NpbmcgdmFsdWVzIHN0ZW1taW5nbHkgKnNvbGVseSogZnJvbSB0aGUgcm93cyB3aXRob3V0IHBvdmVydHkgZGF0YSBhbmQgb25seSBhIGxhYmVsIGRlc2lnbmF0aW5nIHRoZSB5ZWFyCnBvdmVydHlfcmF0ZV9kYXRhICU+JSAKICBncm91cF9ieShuX25hKSAlPiUKICB0YWxseSgpCgpzYXBwbHkocG92ZXJ0eV9yYXRlX2RhdGEsIGNsYXNzKQoKcG92ZXJ0eV9yYXRlX2RhdGEgPC0gcG92ZXJ0eV9yYXRlX2RhdGEgJT4lCiAgZHJvcF9uYSgpICU+JQogIGRwbHlyOjpzZWxlY3QoLU51bWJlciwKICAgICAgICAgICAgICAgIC1OdW1iZXJfc2UsCiAgICAgICAgICAgICAgICAtUGVyY2VudF9zZSwKICAgICAgICAgICAgICAgIC1uX25hLAogICAgICAgICAgICAgICAgLVRvdGFsKSAlPiUKICByZW5hbWUoIlZBTFVFIj1QZXJjZW50KSAlPiUKICBtdXRhdGUoVkFSSUFCTEUgPSAiUG92ZXJ0eV9yYXRlIiwKICAgICAgICAgWUVBUiA9IGFzLm51bWVyaWMoWUVBUiksCiAgICAgICAgIFZBTFVFID0gYXMubnVtZXJpYyhWQUxVRSkpCgpjb2xuYW1lcyhwb3ZlcnR5X3JhdGVfZGF0YSkKYGBgCgojIyBWaW9sZW50IGNyaW1lCgpodHRwczovL3d3dy51Y3JkYXRhdG9vbC5nb3YvU2VhcmNoL0NyaW1lL1N0YXRlL1N0YXRlYnlTdGF0ZS5jZm0KCmBgYHtyfQpsZW5ndGgoY3JpbWVfZGF0YSkKCmNyaW1lX2RhdGEgPC0gY3JpbWVfZGF0YVstKDIxNDM6bGVuZ3RoKGNyaW1lX2RhdGEpKV0KCnggPC0gMjAxNC0xOTc3KzEKCnJlcF9jeWNsZSA8LSAyICsgMiArIHgKCnJlcF9jeWNsZV9jdXQgPC0gMiArIHgKCmRlbGV0ZV9yb3dzIDwtIGMoc2VxKDIsbGVuZ3RoKGNyaW1lX2RhdGEpLHJlcF9jeWNsZSksCiAgICAgICAgICAgICAgICAgc2VxKDMsbGVuZ3RoKGNyaW1lX2RhdGEpLHJlcF9jeWNsZSkpCgpjcmltZV9kYXRhIDwtIGNyaW1lX2RhdGFbLWRlbGV0ZV9yb3dzXQoKY3JpbWVfZGF0YSA8LSBkYXRhLmZyYW1lKGNiaW5kKGNyaW1lX2RhdGEsIHJlcCgxOihsZW5ndGgoY3JpbWVfZGF0YSkvcmVwX2N5Y2xlX2N1dCksZWFjaD1yZXBfY3ljbGVfY3V0KSkpCgpjb2xuYW1lcyhjcmltZV9kYXRhKSA8LSBjKCJTdHJpbmciLCJTVEFURV9HUk9VUCIpCgpjcmltZV9kYXRhIDwtIGNyaW1lX2RhdGEgJT4lCiAgZ3JvdXBfYnkoU1RBVEVfR1JPVVApICU+JQogIGdyb3VwX3NwbGl0KCkKCmNvbHVtbnNfY3JpbWVfZGF0YSA8LSA4CgpjcmltZV9kYXRhIDwtIGNyaW1lX2RhdGEgJT4lCiAgbWFwKH5tdXRhdGUoLiwKICAgICAgICAgICAgICAgU3RhdGUgPSBjYXNlX3doZW4oc3RyX2RldGVjdChTdHJpbmcsICJFc3RpbWF0ZWQgY3JpbWUgaW4gIikgfiBzdWJzdHJpbmcoU3RyaW5nLCBuY2hhcigiRXN0aW1hdGVkIGNyaW1lIGluICIpKzEpKSwKICAgICAgICAgICAgICByb3dfaWQgPSByb3dfbnVtYmVyKCkpKSAlPiUKICBtYXAofmZpbGwoLiwgU3RhdGUpKSAlPiUKICBtYXAofmZpbHRlciguLHJvd19pZCA+IDIpKSAlPiUKICBtYXAofm11dGF0ZSguLAogICAgICAgICAgICAgIFN0cmluZyA9IHBhc3RlMChTdHJpbmcsICIsIiwgU3RhdGUpKSkgJT4lCiAgbWFwKH5kcGx5cjo6c2VsZWN0KC4sU3RyaW5nKSkgJT4lCiAgbWFwKH5zdHJfc3BsaXRfZml4ZWQoLiRTdHJpbmcsIiwiLGNvbHVtbnNfY3JpbWVfZGF0YSArIDEpKSAlPiUKICBtYXAofmRhdGEuZnJhbWUoLikpICU+JQogIG1hcCh+cmVuYW1lKC4sIllFQVIiPVgxLAogICAgICAgICAgICAgICJFeHRyYV9jb2wxIj1YMiwKICAgICAgICAgICAgICAiVkMiPVgzLAogICAgICAgICAgICAgICJFeHRyYV9jb2wyIj1YNCwKICAgICAgICAgICAgICAiRXh0cmFfY29sMyI9WDUsCiAgICAgICAgICAgICAgIkV4dHJhX2NvbDQiPVg2LAogICAgICAgICAgICAgICJFeHRyYV9jb2w1Ij1YNywKICAgICAgICAgICAgICAiRXh0cmFfY29sNiI9WDgsCiAgICAgICAgICAgICAgIlNUQVRFIj1YOSkpICU+JQogIG1hcCh+ZHBseXI6OnNlbGVjdCguLC1jb250YWlucygiRXh0cmFfY29sIikpKSAlPiUKICBtYXAofi54ICU+JSBtdXRhdGVfYWxsKH50cmltd3MoLix3aGljaCA9ICJib3RoIikpKSAlPiUKICBtYXBfZGYoYmluZF9yb3dzKQoKc2FwcGx5KGNyaW1lX2RhdGEsIGNsYXNzKQoKY3JpbWVfZGF0YSA8LSBjcmltZV9kYXRhICU+JQogIG11dGF0ZShWQVJJQUJMRSA9ICJWaW9sX2NyaW1lX2NvdW50IikgJT4lCiAgcmVuYW1lKCJWQUxVRSIgPSBWQykgJT4lCiAgYXMudGliYmxlKCkgJT4lCiAgbXV0YXRlKFlFQVIgPSBhcy5udW1lcmljKFlFQVIpLAogICAgICAgICBWQUxVRSA9IGFzLm51bWVyaWMoVkFMVUUpKQpgYGAKCiMjIFJUQyBsYXdzCgpgYGB7cn0KREFXcGFwZXJfcF82MiA8LSBEQVdwYXBlcltbNjJdXQoKcF82MiA8LSBEQVdwYXBlcl9wXzYyICU+JQogICAgc3Ryc3BsaXQoIlxuIikgJT4lCiAgICB1bmxpc3QoKSAlPiUKICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUKICAgIHNsaWNlKC0oMToyKSkKCmFwcGx5KHBfNjIsIDEsIG5jaGFyKQoKcF82Mls1MyxdICNwaHlzY2lhbCBwYWdlIDYwCgpwXzYyIDwtIHBfNjIgJT4lCiAgICBzbGljZSgtNTMpCgphcHBseShwXzYyLCAxLCBzdHJfY291bnQsICJcXHN7NSx9IikKYXBwbHkocF82MiwgMSwgc3RyX2NvdW50LCAiXFxzezEwLH0iKQphcHBseShwXzYyLCAxLCBzdHJfY291bnQsICJcXHN7MjAsfSIpCmFwcGx5KHBfNjIsIDEsIHN0cl9jb3VudCwgIlxcc3s0MCx9IikKCmhlYWQoY2JpbmQocF82MiwgYXBwbHkocF82MiwgMSwgc3RyX2NvdW50LCAiXFxzezQwLH0iKSkpCgpwXzYyIDwtIHBfNjIgJT4lCiAgICBhcHBseSgxLHN0cl9yZXBsYWNlX2FsbCwgIlxcc3s0MCx9IiwgInxOL0F8IikgJT4lCiAgICBzdHJfcmVwbGFjZV9hbGwoIlxcc3syLDE1fSIsICJ8IikgJT4lCiAgICBhcy5kYXRhLmZyYW1lKCkKCnBfNjIgPC0gc2FwcGx5KHBfNjIkLiwgc3RyX3NwbGl0LCAiXFx8ezEsfSIpCgpzYXBwbHkocF82MiwgbmNoYXIpCgpwXzYyIDwtIGxhcHBseShwXzYyLCBmdW5jdGlvbih4KSB4W25jaGFyKHgpID4gMF0pIAoKcF82MiA8LSBhcy5kYXRhLmZyYW1lKGRvLmNhbGwocmJpbmQsIHBfNjIpKQoKcm93bmFtZXMocF82MikKCnJvd25hbWVzKHBfNjIpIDwtIGMoKQoKY29sbmFtZXMocF82MikgPC0gYygiU1RBVEUiLAogICAgICAgICAgICAgICAgICAgICJFX0RhdGVfUlRDIiwKICAgICAgICAgICAgICAgICAgICAiRnJhY19Zcl9FZmZfWXJfUGFzcyIsCiAgICAgICAgICAgICAgICAgICAgIlJUQ19EYXRlX1NBIikKc2FwcGx5KHBfNjIsIGNsYXNzKQoKcF82MiA8LSBwXzYyICU+JQogIGRwbHlyOjpzZWxlY3QoU1RBVEUsIFJUQ19EYXRlX1NBKSAlPiUKICByZW5hbWUoIlJUQ19MQVdfWUVBUiI9UlRDX0RhdGVfU0EpICU+JQogIG11dGF0ZShSVENfTEFXX1lFQVIgPSBhcy5udW1lcmljKFJUQ19MQVdfWUVBUikpICU+JQogIG11dGF0ZShSVENfTEFXX1lFQVIgPSBjYXNlX3doZW4oUlRDX0xBV19ZRUFSID09IDAgfiBJbmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBSVENfTEFXX1lFQVIpKQoKc2FwcGx5KHBfNjIsIGNsYXNzKQoKaGVhZChwXzYyKQpgYGAKCiMjIENoZWNrcG9pbnQKYGBge3J9CmNvbG5hbWVzKGRlbV9ET05PSFVFKQpjb2xuYW1lcyhkZW1fTE9UVCkKY29sbmFtZXModWVfcmF0ZV9kYXRhKQpjb2xuYW1lcyhwb3ZlcnR5X3JhdGVfZGF0YSkKY29sbmFtZXMoY3JpbWVfZGF0YSkKCmhlYWQoZGVtX0RPTk9IVUUpCmhlYWQoZGVtX0xPVFQpCmhlYWQodWVfcmF0ZV9kYXRhKQpoZWFkKHBvdmVydHlfcmF0ZV9kYXRhKQpoZWFkKGNyaW1lX2RhdGEpCmBgYAoKIyMgSm9pbgoKIyMgRG9ub2h1ZSwgZXQgYWwuCgpgYGB7cn0KRE9OT0hVRV9ERiA8LSBiaW5kX3Jvd3MoZGVtX0RPTk9IVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIHVlX3JhdGVfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgcG92ZXJ0eV9yYXRlX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgIGNyaW1lX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvcHVsYXRpb25fZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgcHNfZGF0YSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJWQVJJQUJMRSIsCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSAiVkFMVUUiKSAlPiUKICBsZWZ0X2pvaW4ocF82MiAsIGJ5ID0gYygiU1RBVEUiKSkgJT4lCiAgbXV0YXRlKFJUQ19MQVcgPSBjYXNlX3doZW4oWUVBUiA+PSBSVENfTEFXX1lFQVIgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpKQoKRE9OT0hVRV9ERiAlPiUKICBncm91cF9ieShZRUFSKSAlPiUKICB0YWxseSgpICU+JQogIGZpbHRlcihuICE9IDUxKSAlPiUKICBwcmludChuPWRpbSguKVsxXSkKCnN1bW1hcnkoYXMuZmFjdG9yKERPTk9IVUVfREYkU1RBVEUpKQoKbWF4KERPTk9IVUVfREYkWUVBUikgLSBtaW4oRE9OT0hVRV9ERiRZRUFSKSArIDEKCkRPTk9IVUVfREYgPC0gRE9OT0hVRV9ERiAlPiUKICBtdXRhdGUoU1RBVEUgPSBmY3RfY29sbGFwc2UoU1RBVEUsICJEaXN0cmljdCBvZiBDb2x1bWJpYSI9YygiRGlzdHJpY3Qgb2YgQ29sdW1iaWEiLCJELkMuIikpKQoKc3VtbWFyeShhcy5mYWN0b3IoRE9OT0hVRV9ERiRTVEFURSkpCiAgCmxlbmd0aChsZXZlbHMoRE9OT0hVRV9ERiRTVEFURSkpCgpET05PSFVFX0RGIDwtIERPTk9IVUVfREYgJT4lCiAgZ3JvdXBfYnkoU1RBVEUsIFlFQVIpICU+JQogIHN1bW1hcmlzZV9hbGwofm5hLm9taXQodW5pcXVlKC4pKSkgJT4lCiAgdW5ncm91cCgpICMgVGhpcyBpZGVudGlmaWVzIHVuaXF1ZSBvYnNlcnZhdGlvbnMsIGNvYWxlc2NlcyByb3dzIGFjY29yZGluZyB0byB0aGUgZ3JvdXBpbmcgdmFyaWFibGUocyksIGFuZCBnZXRzIHJpZCBvZiBvZiB1bml0cyB0aGF0IGhhdmUgaW5jb21wbGV0ZSBkYXRhLiBUaGlzIGdpdmVzIHJldHVybnMgYSBkYXRhZnJhbWUgd2l0aCB0aGUgbW9zdCBjb21wbGV0ZSBpbmZvcm1hdGlvbi4KCnN1bW1hcnkoYXMuZmFjdG9yKERPTk9IVUVfREYkU1RBVEUpKSAKCmJhc2VsaW5lX3llYXIgPC0gbWluKERPTk9IVUVfREYkWUVBUikKY2Vuc29yaW5nX3llYXIgPC0gbWF4KERPTk9IVUVfREYkWUVBUikKCiMgTmVlZCB0byBmaXggdGhpcyB0byBlbnN1cmUgc2V2ZXJlIGJpYXMgaXMgbm90IGludHJvZHVjZWQgYnkgcHJldmFsZW50ICJjYXNlcyIKCkRPTk9IVUVfREYgPC0gRE9OT0hVRV9ERiAlPiUKICBtdXRhdGUoVElNRV8wID0gYmFzZWxpbmVfeWVhciwKICAgICAgICAgVElNRV9JTkYgPSBjZW5zb3JpbmdfeWVhcikgJT4lCiAgZmlsdGVyKFJUQ19MQVdfWUVBUiA+IFRJTUVfMCkKCkRPTk9IVUVfREYgPC0gRE9OT0hVRV9ERiAlPiUKICBtdXRhdGUoVmlvbF9jcmltZV9yYXRlXzFrID0gKFZpb2xfY3JpbWVfY291bnQqMTAwMCkvUG9wdWxhdGlvbiwKICAgICAgICAgVmlvbF9jcmltZV9yYXRlXzFrX2xvZyA9IGxvZyhWaW9sX2NyaW1lX3JhdGVfMWspLAogICAgICAgICBQb3B1bGF0aW9uX2xvZyA9IGxvZyhQb3B1bGF0aW9uKSkKCnN1bW1hcnkoZHJvcGxldmVscyhhcy5mYWN0b3IoRE9OT0hVRV9ERiRTVEFURSkpKQoKbGVuZ3RoKHN1bW1hcnkoZHJvcGxldmVscyhhcy5mYWN0b3IoRE9OT0hVRV9ERiRTVEFURSkpKSkKYGBgCgojIyBMb3R0IGFuZCBNdXN0YXJkCgpgYGB7cn0KTE9UVF9ERiA8LSBiaW5kX3Jvd3MoZGVtX0xPVFQsCiAgICAgICAgICAgICAgICAgICAgIHVlX3JhdGVfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgcG92ZXJ0eV9yYXRlX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgIGNyaW1lX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgIHBvcHVsYXRpb25fZGF0YSwKICAgICAgICAgICAgICAgICAgICAgcHNfZGF0YSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJWQVJJQUJMRSIsCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSAiVkFMVUUiKSAlPiUKICBsZWZ0X2pvaW4ocF82MiAsIGJ5ID0gYygiU1RBVEUiKSkgJT4lCiAgbXV0YXRlKFJUQ19MQVcgPSBjYXNlX3doZW4oWUVBUiA+PSBSVENfTEFXX1lFQVIgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpKQoKTE9UVF9ERiAlPiUKICBncm91cF9ieShZRUFSKSAlPiUKICB0YWxseSgpICU+JQogIGZpbHRlcihuICE9IDUxKSAlPiUKICBwcmludChuPWRpbSguKVsxXSkKCnN1bW1hcnkoYXMuZmFjdG9yKExPVFRfREYkU1RBVEUpKQoKbWF4KExPVFRfREYkWUVBUikgLSBtaW4oTE9UVF9ERiRZRUFSKSArIDEKCkxPVFRfREYgPC0gTE9UVF9ERiAlPiUKICBtdXRhdGUoU1RBVEUgPSBmY3RfY29sbGFwc2UoU1RBVEUsICJEaXN0cmljdCBvZiBDb2x1bWJpYSI9YygiRGlzdHJpY3Qgb2YgQ29sdW1iaWEiLCJELkMuIikpKQoKc3VtbWFyeShhcy5mYWN0b3IoTE9UVF9ERiRTVEFURSkpCiAgCmxlbmd0aChsZXZlbHMoTE9UVF9ERiRTVEFURSkpCgpMT1RUX0RGIDwtIExPVFRfREYgJT4lCiAgZ3JvdXBfYnkoU1RBVEUsIFlFQVIpICU+JQogIHN1bW1hcmlzZV9hbGwofm5hLm9taXQodW5pcXVlKC4pKSkgJT4lCiAgdW5ncm91cCgpICMgVGhpcyBpZGVudGlmaWVzIHVuaXF1ZSBvYnNlcnZhdGlvbnMsIGNvYWxlc2NlcyByb3dzIGFjY29yZGluZyB0byB0aGUgZ3JvdXBpbmcgdmFyaWFibGUocyksIGFuZCBnZXRzIHJpZCBvZiBvZiB1bml0cyB0aGF0IGhhdmUgaW5jb21wbGV0ZSBkYXRhLiBUaGlzIGdpdmVzIHJldHVybnMgYSBkYXRhZnJhbWUgd2l0aCB0aGUgbW9zdCBjb21wbGV0ZSBpbmZvcm1hdGlvbi4KCnN1bW1hcnkoYXMuZmFjdG9yKExPVFRfREYkU1RBVEUpKSAKCmJhc2VsaW5lX3llYXIgPC0gbWluKExPVFRfREYkWUVBUikKY2Vuc29yaW5nX3llYXIgPC0gbWF4KExPVFRfREYkWUVBUikKCiMgTmVlZCB0byBmaXggdGhpcyB0byBlbnN1cmUgc2V2ZXJlIGJpYXMgaXMgbm90IGludHJvZHVjZWQgYnkgcHJldmFsZW50ICJjYXNlcyIKCkxPVFRfREYgPC0gTE9UVF9ERiAlPiUKICBtdXRhdGUoVElNRV8wID0gYmFzZWxpbmVfeWVhciwKICAgICAgICAgVElNRV9JTkYgPSBjZW5zb3JpbmdfeWVhcikgJT4lCiAgZmlsdGVyKFJUQ19MQVdfWUVBUiA+IFRJTUVfMCkKCkxPVFRfREYgPC0gTE9UVF9ERiAlPiUKICBtdXRhdGUoVmlvbF9jcmltZV9yYXRlXzFrID0gKFZpb2xfY3JpbWVfY291bnQqMTAwMCkvUG9wdWxhdGlvbiwKICAgICAgICAgVmlvbF9jcmltZV9yYXRlXzFrX2xvZyA9IGxvZyhWaW9sX2NyaW1lX3JhdGVfMWspLAogICAgICAgICBQb3B1bGF0aW9uX2xvZyA9IGxvZyhQb3B1bGF0aW9uKSkKCnN1bW1hcnkoZHJvcGxldmVscyhhcy5mYWN0b3IoTE9UVF9ERiRTVEFURSkpKQoKbGVuZ3RoKHN1bW1hcnkoZHJvcGxldmVscyhhcy5mYWN0b3IoTE9UVF9ERiRTVEFURSkpKSkKYGBgCgojICoqRGF0YSBFeHBsb3JhdGlvbioqCioqKgoKYGBge3J9CnNhcHBseShET05PSFVFX0RGLCBjbGFzcykKCkRPTk9IVUVfREYgJT4lCiAgbXV0YXRlKFZpb2xfY3JpbWVfcmF0ZV8xMDBrX2xvZyA9IGxvZygoVmlvbF9jcmltZV9jb3VudCoxMDAwMDApL1BvcHVsYXRpb24pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZRUFSLCB5ID0gVmlvbF9jcmltZV9yYXRlXzEwMGtfbG9nLCBjb2xvciA9IFNUQVRFKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkgKwogIGdlb21fbGluZShhZXMoZ3JvdXA9U1RBVEUpLAogICAgICAgICAgICBzaXplID0gMC41LAogICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBET05PSFVFX0RGICU+JQogICAgICAgICAgICAgIG11dGF0ZShWaW9sX2NyaW1lX3JhdGVfMTAwa19sb2cgPSBsb2coKFZpb2xfY3JpbWVfY291bnQqMTAwMDAwKS9Qb3B1bGF0aW9uKSkgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKFlFQVIgPT0gbGFzdChZRUFSKSksCiAgICAgICAgICAgIGFlcyhsYWJlbCA9IFNUQVRFLAogICAgICAgICAgICAgICAgeCA9IFlFQVIsCiAgICAgICAgICAgICAgICB5ID0gVmlvbF9jcmltZV9yYXRlXzEwMGtfbG9nKSwKICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgIGFscGhhID0gMSwKICAgICAgICAgICAgbnVkZ2VfeCA9IDEwLAogICAgICAgICAgICBkaXJlY3Rpb24gPSAieSIsCiAgICAgICAgICAgIGhqdXN0ID0gMSwKICAgICAgICAgICAgdmp1c3QgPSAxLAogICAgICAgICAgICBzZWdtZW50LnNpemUgPSAwLjI1LAogICAgICAgICAgICBzZWdtZW50LmFscGhhID0gMC4yNSwKICAgICAgICAgICAgZm9yY2UgPSAxLAogICAgICAgICAgICBtYXguaXRlciA9IDk5OTkpICsKICBndWlkZXMoY29sb3IgPSBGQUxTRSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTk4MCwgMjAxNSwgYnkgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygxOTgwLCAyMDE1KSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYyhzZXEoMTk4MCwgMjAxMCwgYnkgPSAxKSwgcmVwKCIiLCA1KSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDMuNSwgOC41LCBieSA9IDAuNSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMy41LCA4LjUpKSArCiAgbGFicyh0aXRsZSA9ICJTdGF0ZXMgaGF2ZSBkaWZmZXJlbnQgbGV2ZWxzIG9mIGNyaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gImxuKHZpb2xlbnQgY3JpbWVzIHBlciAxMDAsMDAwIHBlb3BsZSkiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCkRPTk9IVUVfREYgJT4lCiAgZ3JvdXBfYnkoWUVBUikgJT4lCiAgc3VtbWFyaXNlKFZpb2xfY3JpbWVfY291bnQgPSBzdW0oVmlvbF9jcmltZV9jb3VudCksCiAgICAgICAgICAgIFBvcHVsYXRpb24gPSBzdW0oUG9wdWxhdGlvbiksCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIG11dGF0ZShWaW9sX2NyaW1lX3JhdGVfMTAwa19sb2cgPSBsb2coKFZpb2xfY3JpbWVfY291bnQqMTAwMDAwKS9Qb3B1bGF0aW9uKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWUVBUiwgeSA9IFZpb2xfY3JpbWVfcmF0ZV8xMDBrX2xvZykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTgwLCAyMDEwLCBieSA9IDEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDE5ODAsIDIwMTApLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKHNlcSgxOTgwLCAyMDEwLCBieSA9IDEpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoNS43NSwgNi43NSwgYnkgPSAwLjI1KSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyg1Ljc1LCA2Ljc1KSkgKwogIGxhYnModGl0bGUgPSAiQ3JpbWUgcmF0ZXMgZmx1Y3R1YXRlIG92ZXIgdGltZSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJsbih2aW9sZW50IGNyaW1lcyBwZXIgMTAwLDAwMCBwZW9wbGUpIikgKwogIHRoZW1lX21pbmltYWwoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpgYGAKCiMgKipEYXRhIEFuYWx5c2lzKioKKioqCgojIyBEb25vaHVlLCBldCBhbC4KClNvbWUgY29kZSB0YWtlbiBmcm9tIGh0dHA6Ly9rYXJ0aHVyLm9yZy8yMDE5L2ltcGxlbWVudGluZy1maXhlZC1lZmZlY3RzLXBhbmVsLW1vZGVscy1pbi1yLmh0bWwKCmBgYHtyfQpkX3BhbmVsX0RPTk9IVUUgPC0gcGRhdGEuZnJhbWUoRE9OT0hVRV9ERiwgaW5kZXg9YygiU1RBVEUiLCAiWUVBUiIpKQoKRE9OT0hVRV9PVVRQVVQgPC0gcGxtKFZpb2xfY3JpbWVfcmF0ZV8xa19sb2cgfgogICAgICAgICAgICAgICAgICAgICAgICBSVENfTEFXICsKICAgICAgICAgICAgICAgICAgICAgICAgV2hpdGVfTWFsZV8xNV90b18xOV95ZWFycyArCiAgICAgICAgICAgICAgICAgICAgICAgIFdoaXRlX01hbGVfMjBfdG9fMzlfeWVhcnMgKwogICAgICAgICAgICAgICAgICAgICAgICBCbGFja19NYWxlXzE1X3RvXzE5X3llYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgQmxhY2tfTWFsZV8yMF90b18zOV95ZWFycyArCiAgICAgICAgICAgICAgICAgICAgICAgIE90aGVyX01hbGVfMTVfdG9fMTlfeWVhcnMgKwogICAgICAgICAgICAgICAgICAgICAgICBPdGhlcl9NYWxlXzIwX3RvXzM5X3llYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgVW5lbXBsb3ltZW50X3JhdGUgKwogICAgICAgICAgICAgICAgICAgICAgICBQb3ZlcnR5X3JhdGUgKyAKICAgICAgICAgICAgICAgICAgICAgICAgUG9wdWxhdGlvbl9sb2cgKyAKICAgICAgICAgICAgICAgICAgICAgICAgcG9saWNlX3Blcl8xMDBrX2xhZywKICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdCA9ICJ0d293YXlzIiwKICAgICAgICAgICAgICAgICAgICAgIG1vZGVsID0gIndpdGhpbiIsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRfcGFuZWxfRE9OT0hVRSkKCnN1bW1hcnkoRE9OT0hVRV9PVVRQVVQpCgpET05PSFVFX09VVFBVVF9USURZIDwtIHRpZHkoRE9OT0hVRV9PVVRQVVQsIGNvbmYuaW50ID0gMC45NSkKCkRPTk9IVUVfT1VUUFVUX1RJRFkkQW5hbHlzaXMgPC0gIkFuYWx5c2lzIDEiCmBgYAoKIyMgTG90dCBhbmQgTXVzdGFyZAoKU29tZSBjb2RlIHRha2VuIGZyb20gaHR0cDovL2thcnRodXIub3JnLzIwMTkvaW1wbGVtZW50aW5nLWZpeGVkLWVmZmVjdHMtcGFuZWwtbW9kZWxzLWluLXIuaHRtbAoKYGBge3J9CkxPVFRfdmFyaWFibGVzIDwtIExPVFRfREYgJT4lCiAgZHBseXI6OnNlbGVjdChSVENfTEFXLAogICAgICAgICAgICAgICAgY29udGFpbnMoYygiV2hpdGUiLCJCbGFjayIsIk90aGVyIikpLAogICAgICAgICAgICAgICAgVW5lbXBsb3ltZW50X3JhdGUsCiAgICAgICAgICAgICAgICBQb3ZlcnR5X3JhdGUsCiAgICAgICAgICAgICAgICBQb3B1bGF0aW9uX2xvZywKICAgICAgICAgICAgICAgIHBvbGljZV9wZXJfMTAwa19sYWcpICU+JQogIGNvbG5hbWVzKCkKCkxPVFRfZm1sYSA8LSBhcy5mb3JtdWxhKHBhc3RlKCJWaW9sX2NyaW1lX3JhdGVfMWtfbG9nIH4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZShMT1RUX3ZhcmlhYmxlcywgY29sbGFwc2UgPSAiICsgIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICApCgpkX3BhbmVsX0xPVFQgPC0gcGRhdGEuZnJhbWUoTE9UVF9ERiwgaW5kZXg9YygiU1RBVEUiLCAiWUVBUiIpKQoKTE9UVF9PVVRQVVQgPC0gcGxtKExPVFRfZm1sYSwKICAgICAgICAgICAgICAgICAgICAgIG1vZGVsID0gIndpdGhpbiIsCiAgICAgICAgICAgICAgICAgICBlZmZlY3QgPSAidHdvd2F5cyIsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRfcGFuZWxfTE9UVCkKCnN1bW1hcnkoTE9UVF9PVVRQVVQpCgpMT1RUX09VVFBVVF9USURZIDwtIHRpZHkoTE9UVF9PVVRQVVQsIGNvbmYuaW50ID0gMC45NSkKCkxPVFRfT1VUUFVUX1RJRFkkQW5hbHlzaXMgPC0gIkFuYWx5c2lzIDIiCmBgYAoKIyMgQ29tcGFyaW5nIGFuYWx5c2VzCgpgYGB7cn0KY29tcGFyaW5nX2FuYWx5c2VzIDwtIERPTk9IVUVfT1VUUFVUX1RJRFkgJT4lCiAgYmluZF9yb3dzKExPVFRfT1VUUFVUX1RJRFkpICU+JQogIGZpbHRlcih0ZXJtID09ICJSVENfTEFXVFJVRSIpCgpsaWJyYXJ5KGdyaWQpCgpjb21wYXJpbmdfYW5hbHlzZXNfcGxvdCA8LSBnZ3Bsb3QoY29tcGFyaW5nX2FuYWx5c2VzKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSBBbmFseXNpcywgeSA9IGVzdGltYXRlKSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHggPSBBbmFseXNpcywgeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoKSwgd2lkdGggPSAwLjI1KSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZCIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0wLjIsIDAuMiwgYnkgPSAwLjA1KSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKC0wLjIsIDAuMiwgYnkgPSAwLjA1KSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygtMC4yLDAuMikpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLCB5ID0gMC4xMjUsIHhlbmQgPSAxLCB5ZW5kID0gMC4xNzUpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGFuZ2xlID0gNDUsIGVuZHMgPSAibGFzdCIsIHR5cGUgPSAib3BlbiIpLAogICAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgICAgY29sb3IgPSAiZ3JlZW4iLAogICAgICAgICAgICAgICBsaW5lZW5kID0gImJ1dHQiLAogICAgICAgICAgICAgICBsaW5lam9pbiA9ICJtaXRyZSIpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAyLCB5ID0gLTAuMTI1LCB4ZW5kID0gMiwgeWVuZCA9IC0wLjE3NSksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coYW5nbGUgPSA0NSwgZW5kcyA9ICJsYXN0IiwgdHlwZSA9ICJvcGVuIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLAogICAgICAgICAgICAgICBsaW5lZW5kID0gImJ1dHQiLAogICAgICAgICAgICAgICBsaW5lam9pbiA9ICJtaXRyZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKyAKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpICsKICBsYWJzKHRpdGxlID0gIkVmZmVjdCBlc3RpbWF0ZSBvbiBsbih2aW9sZW50IGNyaW1lcyBwZXIgMTAwLDAwMCBwZW9wbGUpIiwKICAgICAgIHkgPSAiRWZmZWN0IGVzdGltYXRlICg5NSUgQ0kpIikKCmNvbXBhcmluZ19hbmFseXNlc19wbG90CmBgYAoKIyBNdWx0aWNvbGxpbmVhcml0eSBhbmFseXNpcwoKSG93IGRpZCB0aGUgYWJvdmUgaGFwcGVuPwoKVGhlIGFuYWx5c2lzIGRhdGFmcmFtZXMgYXJlIHZlcnkgc2ltaWxhciB5ZXQgcmVuZGVyZWQgdmVyeSBkaWZmZXJlbnQgcmVzdWx0cy4gCgpgYGB7cn0KYWxsX2VxdWFsKHRhcmdldCA9IERPTk9IVUVfREYsCiAgICAgICAgICBjdXJyZW50ID0gTE9UVF9ERiwKICAgICAgICAgIGlnbm9yZV9jb2xfb3JkZXIgPSBUUlVFLAogICAgICAgICAgaWdub3JlX3Jvd19vcmRlciA9IFRSVUUpCgpkaW0oRE9OT0hVRV9ERilbMV0gPT0gZGltKExPVFRfREYpWzFdCmBgYAoKVGhlIG9ubHkgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gZGF0YWZyYW1lcyByZXN0cyBpbiBob3cgdGhlIGRlbW9ncmFwaGljIHZhcmlhYmxlcyB3ZXJlIHBhcmFtZXRlcml6ZWQuCgpgYGB7cn0KRE9OT0hVRV9ERiAlPiUKICBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKCJ5ZWFycyIpKSAlPiUKICBjb2xuYW1lcygpCgpMT1RUX0RGICU+JQogIGRwbHlyOjpzZWxlY3QoY29udGFpbnMoInllYXJzIikpICU+JQogIGNvbG5hbWVzKCkKYGBgCgpDbGVhcmx5LCB0aGlzIGhhZCBhbiBlZmZlY3Qgb24gdGhlIHJlc3VsdHMgb2YgdGhlIGFuYWx5c2lzLiAKCkxldCdzIGV4cGxvcmUgaG93IHRoaXMgb2NjdXJlZC4gCgpXaGVuIHNlZW1pbmdseSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYXJlIGhpZ2hseSByZWxhdGVkIHRvIG9uZSBhbm90aGVyLCB0aGUgcmVsYXRpb25zaGlwcyBlc3RpbWF0ZWQgaW4gYW4gYW5hbHlzaXMgbWF5IGJlIGRpc3RvcnRlZC4gCgpJbiByZWdyZXNzaW9uIGFuYWx5c2lzLCB0aGlzIGRpc3RvcnRpb24gaXMgb2Z0ZW4gYSBieXByb2R1Y3Qgb2YgYSB2aW9sYXRpb24gb2YgdGhlIGluZGVwZW5kZW5jZSBhc3N1bXB0aW9uLiBUaGlzIGRpc3RvcnRpb24sIGlmIGxhcmdlIGVub3VnaCwgY2FuIGltcGFjdCBzdGF0aXN0aWNhbCBpbmZlcmVuY2UuIAoKVGhlcmUgYXJlIHNldmVyYWwgd2F5cyB3ZSBjYW4gZGlhZ25vc2UgbXVsdGljb2xsaW5lYXJpdHkuCgojIyMgQ29ycmVsYXRpb24KCkFnYWluLCBtdWx0aWNvbGxpbmVhcml0eSBvZnRlbiBvY2N1cnMgd2hlbiBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYXJlIGhpZ2hseSByZWxhdGVkIHRvIG9uZSBhbm90aGVyLiBDb25zZXF1ZW50bHksIHdlIGNhbiBldmFsdWF0ZSB0aGVzZSByZWxhdGlvbnNoaXBzIGJlIGV4YW1pbmluZyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB2YXJpYWJsZSBwYWlycy4KCjxzdHlsZT4KZGl2LmJsdWUgeyBiYWNrZ3JvdW5kLWNvbG9yOiNlNmYwZmY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAiYmx1ZSI+CgpJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IG11bHRpY29sbGluZWFyaXR5IGFuZCBjb3JyZWxhdGlvbiBhcmUgbm90IG9uZSBhbmQgdGhlIHNhbWUuIENvcnJlbGF0aW9uIGNhbiBiZSB0aG91Z2h0IG9mIGFzIHRoZSBzdHJlbmd0aCBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdmFyaWFibGVzLiBPbiB0aGUgb3RoZXIgaGFuZCwgbXVsdGljb2xsaW5lYXJpdHkgY2FuIGJlIHRob3VnaHQgb2YgdGhlIHRoZSB2aW9sYXRpb24gb2YgdGhlIGluZGVwZW5kZW5jZSBhc3N1bXB0aW9uIHRoYXQgaXMgYSBjb25zZXF1ZW5jZSBvZiB0aGlzIGNvcnJlbGF0aW9uIGluIGEgcmVncmVzc2lvbiBhbmFseXNpcy4gCgo8L2Rpdj4KCiMjIyMgU2NhdHRlcnBsb3RzCgpgYGB7cn0KY29sbmFtZXMoRE9OT0hVRV9ERikKCkRPTk9IVUVfREYgJT4lIAogIGRwbHlyOjpzZWxlY3QoUlRDX0xBVywKICAgICAgICAgICAgICAgIFZpb2xfY3JpbWVfcmF0ZV8xa19sb2csCiAgICAgICAgICAgICAgICBVbmVtcGxveW1lbnRfcmF0ZSwKICAgICAgICAgICAgICAgIFBvdmVydHlfcmF0ZSwKICAgICAgICAgICAgICAgIFBvcHVsYXRpb25fbG9nKSAlPiUgCiAgZ2dwYWlycyguLAogICAgICAgICAgY29sdW1ucyA9IGMoMjo1KSwKICAgICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gd3JhcCgic21vb3RoX2xvZXNzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjEpKSkKCkxPVFRfREYgJT4lIAogIGRwbHlyOjpzZWxlY3QoUlRDX0xBVywKICAgICAgICAgICAgICAgIFZpb2xfY3JpbWVfcmF0ZV8xa19sb2csCiAgICAgICAgICAgICAgICBVbmVtcGxveW1lbnRfcmF0ZSwKICAgICAgICAgICAgICAgIFBvdmVydHlfcmF0ZSwKICAgICAgICAgICAgICAgIFBvcHVsYXRpb25fbG9nKSAlPiUgCiAgZ2dwYWlycyguLAogICAgICAgICAgY29sdW1ucyA9IGMoMjo1KSwKICAgICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gd3JhcCgic21vb3RoX2xvZXNzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjEpKSkKYGBgCgojIyMjIEhlYXRtYXBzCgpgYGB7cn0KY29yX0RPTk9IVUVfZGVtIDwtIGNvcihET05PSFVFX0RGICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKCJfeWVhcnMiKSkpCgpjb3JyX21hdF9ET05PSFVFIDwtIGdnY29ycnBsb3QoY29yX0RPTk9IVUVfZGVtLAogICAgICAgICAgIHRsLmNleCA9IDYsCiAgICAgICAgICAgaGMub3JkZXIgPSBUUlVFLAogICAgICAgICAgIGNvbG9ycyA9IGMoInJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAid2hpdGUiLAogICAgICAgICAgICAgICAgICAgICAgInJlZCIpLAogICAgICAgICAgIG91dGxpbmUuY29sb3IgPSAidHJhbnNwYXJlbnQiLAogICAgICAgICAgIHRpdGxlID0gIkNvcnJlbGF0aW9uIE1hdHJpeCwgQW5hbHlzaXMgMSIsCiAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gVGVYKCIkXFxyaG8kIikpCgpjb3JyX21hdF9ET05PSFVFCgpjb3JfTE9UVF9kZW0gPC0gY29yKExPVFRfREYgJT4lIGRwbHlyOjpzZWxlY3QoY29udGFpbnMoIl95ZWFycyIpKSkKCmNvcnJfbWF0X0xPVFQgPC0gZ2djb3JycGxvdChjb3JfTE9UVF9kZW0sCiAgICAgICAgICAgdGwuY2V4ID0gNiwKICAgICAgICAgICBoYy5vcmRlciA9IFRSVUUsCiAgICAgICAgICAgY29sb3JzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICJ3aGl0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAicmVkIiksCiAgICAgICAgICAgb3V0bGluZS5jb2xvciA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgdGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4LCBBbmFseXNpcyAyIiwKICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBUZVgoIiRcXHJobyQiKSkKCmNvcnJfbWF0X0xPVFQKYGBgCgojIyMgQ29lZmZpY2llbnQgZXN0aW1hdGUgaW5zdGFiaWxpdHkKCmBgYHtyfQpzaW1zIDwtIDI1MAoKIyBET05PSFVFCgojIHJvdW5kKGRpbShET05PSFVFX0RGKVsxXS8yKQpzYW1wc19ET05PSFVFIDwtIGxhcHBseShyZXAoZGltKERPTk9IVUVfREYpWzFdLTEsIHNpbXMpLAogICAgICAgZnVuY3Rpb24oeClET05PSFVFX0RGW3NhbXBsZShucm93KERPTk9IVUVfREYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IHgsIHJlcGxhY2UgPSBGQUxTRSksXSkKCmZpdF9ubHNfb25fYm9vdHN0cmFwX0RPTk9IVUUgPC0gZnVuY3Rpb24oc3BsaXQpewogIHBsbShWaW9sX2NyaW1lX3JhdGVfMWtfbG9nIH4KICAgICAgICAgICAgICAgICAgICAgICAgUlRDX0xBVyArCiAgICAgICAgICAgICAgICAgICAgICAgIFdoaXRlX01hbGVfMTVfdG9fMTlfeWVhcnMgKwogICAgICAgICAgICAgICAgICAgICAgICBXaGl0ZV9NYWxlXzIwX3RvXzM5X3llYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgQmxhY2tfTWFsZV8xNV90b18xOV95ZWFycyArCiAgICAgICAgICAgICAgICAgICAgICAgIEJsYWNrX01hbGVfMjBfdG9fMzlfeWVhcnMgKwogICAgICAgICAgICAgICAgICAgICAgICBPdGhlcl9NYWxlXzE1X3RvXzE5X3llYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgT3RoZXJfTWFsZV8yMF90b18zOV95ZWFycyArCiAgICAgICAgICAgICAgICAgICAgICAgIFVuZW1wbG95bWVudF9yYXRlICsKICAgICAgICAgICAgICAgICAgICAgICAgUG92ZXJ0eV9yYXRlICsgCiAgICAgICAgICAgICAgICAgICAgICAgIFBvcHVsYXRpb25fbG9nICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHBvbGljZV9wZXJfMTAwa19sYWcsCiAgICAgIGRhdGEgPSBkYXRhLmZyYW1lKHNwbGl0KSwKICAgICAgaW5kZXggPSBjKCJTVEFURSIsIllFQVIiKSwKICAgICAgbW9kZWwgPSAid2l0aGluIiwKICAgICAgZWZmZWN0ID0gInR3b3dheXMiKQp9CiAgCnNhbXBzX21vZGVsc19ET05PSFVFIDwtIGxhcHBseShzYW1wc19ET05PSFVFLCBmaXRfbmxzX29uX2Jvb3RzdHJhcF9ET05PSFVFKQoKc2FtcHNfbW9kZWxzX0RPTk9IVUUgPC0gc2FtcHNfbW9kZWxzX0RPTk9IVUUgJT4lCiAgbWFwKHRpZHkpCgpuYW1lcyhzYW1wc19tb2RlbHNfRE9OT0hVRSkgPC0gcGFzdGUwKCJET05PSFVFXyIsMTpsZW5ndGgoc2FtcHNfbW9kZWxzX0RPTk9IVUUpKQoKc2ltdWxhdGlvbnNfRE9OT0hVRSA8LSBzYW1wc19tb2RlbHNfRE9OT0hVRSAlPiUKICBiaW5kX3Jvd3MoLmlkID0gIklEIikgJT4lCiAgbXV0YXRlKEFuYWx5c2lzID0gIkFuYWx5c2lzIDEiKQoKIyMgTE9UVAoKc2FtcHNfTE9UVCA8LSBsYXBwbHkocmVwKHJvdW5kKGRpbShMT1RUX0RGKVsxXS8yKSwgc2ltcyksCiAgICAgICBmdW5jdGlvbih4KSBMT1RUX0RGW3NhbXBsZShucm93KExPVFRfREYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IHgsIHJlcGxhY2UgPSBGQUxTRSksXSkKCmZpdF9ubHNfb25fYm9vdHN0cmFwX0xPVFQgPC0gZnVuY3Rpb24oc3BsaXQpewogIHBsbShMT1RUX2ZtbGEsCiAgICAgIGRhdGEgPSBkYXRhLmZyYW1lKHNwbGl0KSwKICAgICAgaW5kZXggPSBjKCJTVEFURSIsIllFQVIiKSwKICAgICAgbW9kZWwgPSAid2l0aGluIiwKICAgICAgZWZmZWN0ID0gInR3b3dheXMiKQp9CiAgCnNhbXBzX21vZGVsc19MT1RUIDwtIGxhcHBseShzYW1wc19MT1RULCBmaXRfbmxzX29uX2Jvb3RzdHJhcF9MT1RUKQoKc2FtcHNfbW9kZWxzX0xPVFQgPC0gc2FtcHNfbW9kZWxzX0xPVFQgJT4lCiAgbWFwKHRpZHkpCgpuYW1lcyhzYW1wc19tb2RlbHNfTE9UVCkgPC0gcGFzdGUwKCJMT1RUXyIsMTpsZW5ndGgoc2FtcHNfbW9kZWxzX0xPVFQpKQoKc2ltdWxhdGlvbnNfTE9UVCA8LSBzYW1wc19tb2RlbHNfTE9UVCAlPiUKICBiaW5kX3Jvd3MoLmlkID0gIkFuYWx5c2lzIikgJT4lCiAgbXV0YXRlKEFuYWx5c2lzID0gIkFuYWx5c2lzIDIiKQoKc2ltdWxhdGlvbnMgPC0gYmluZF9yb3dzKHNpbXVsYXRpb25zX0RPTk9IVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0aW9uc19MT1RUKQoKc2ltdWxhdGlvbl9wbG90IDwtIHNpbXVsYXRpb25zICU+JQogIGZpbHRlcih0ZXJtPT0iUlRDX0xBV1RSVUUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBBbmFseXNpcywgeSA9IGVzdGltYXRlKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMjUsCiAgICAgICAgICAgICAgd2lkdGggPSAwLjEpICsgCiAgbGFicyh0aXRsZSA9ICJDb2VmZmljaWVudCBpbnN0YWJpbGl0eSIsCiAgICAgICBzdWJ0aXRsZSA9ICJFc3RpbWF0ZXMgc2Vuc2l0aXZlIHRvIG9ic2VydmF0aW9uIGRlbGV0aW9ucyIsCiAgICAgICB4ID0gIlRlcm0iLAogICAgICAgeSA9ICJDb2VmZmljaWVudCIsCiAgICAgICBjYXB0aW9uID0gIlJlc3VsdHMgZnJvbSBzaW11bGF0aW9ucyIpICsgCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpzaW11bGF0aW9uX3Bsb3QKYGBgCgojIyMgVklGCgpgYGB7cn0KZGVzaWduLm1hdHJpeCA8LSBhcy5kYXRhLmZyYW1lKG1vZGVsLm1hdHJpeChET05PSFVFX09VVFBVVCkpCgpkZXNpZ24ubWF0cml4JFZpb2xfY3JpbWVfcmF0ZV8xa19sb2cgPC0gcGxtOjpXaXRoaW4oCiAgZF9wYW5lbF9ET05PSFVFJFZpb2xfY3JpbWVfcmF0ZV8xa19sb2cpCgpsbV9ET05PSFVFIDwtIGxtKFZpb2xfY3JpbWVfcmF0ZV8xa19sb2cgfgogICAgICAgICAgICAgICAgICAgICAgICBSVENfTEFXVFJVRSArICMgbG9naWNhbCBjbGFzcyBjaGFuZ2VzIHZhcmlhYmxlIG5hbWUgYWZ0ZXIgaW5pdGFsIG1vZGVsCiAgICAgICAgICAgICAgICAgICAgICAgIFdoaXRlX01hbGVfMTVfdG9fMTlfeWVhcnMgKwogICAgICAgICAgICAgICAgICAgICAgICBXaGl0ZV9NYWxlXzIwX3RvXzM5X3llYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgQmxhY2tfTWFsZV8xNV90b18xOV95ZWFycyArCiAgICAgICAgICAgICAgICAgICAgICAgIEJsYWNrX01hbGVfMjBfdG9fMzlfeWVhcnMgKwogICAgICAgICAgICAgICAgICAgICAgICBPdGhlcl9NYWxlXzE1X3RvXzE5X3llYXJzICsKICAgICAgICAgICAgICAgICAgICAgICAgT3RoZXJfTWFsZV8yMF90b18zOV95ZWFycyArCiAgICAgICAgICAgICAgICAgICAgICAgIFVuZW1wbG95bWVudF9yYXRlICsKICAgICAgICAgICAgICAgICAgICAgICAgUG92ZXJ0eV9yYXRlICsgCiAgICAgICAgICAgICAgICAgICAgICAgIFBvcHVsYXRpb25fbG9nICsKICAgICAgICAgICAgICAgcG9saWNlX3Blcl8xMDBrX2xhZywKICAgICAgICAgICAgIGRhdGEgPSBkZXNpZ24ubWF0cml4KQoKCnZpZihsbV9ET05PSFVFKQoKdmlmX0RPTk9IVUUgPC0gdmlmKGxtX0RPTk9IVUUpCgp2aWZfRE9OT0hVRSA8LSB2aWZfRE9OT0hVRSAlPiUKICBhc190aWJibGUoKSAlPiUKICBjYmluZCguLCBuYW1lcyh2aWZfRE9OT0hVRSkpICU+JQogIGFzX3RpYmJsZSgpCiAgCmNvbG5hbWVzKHZpZl9ET05PSFVFKSA8LSBjKCJWSUYiLCAiVmFyaWFibGUiKQoKbWF4X3ZpZl9ET05PSFVFIDwtIG1heCh2aWYobG1fRE9OT0hVRSkpIApgYGAKCmBgYHtyfQpkZXNpZ24ubWF0cml4IDwtIGFzLmRhdGEuZnJhbWUobW9kZWwubWF0cml4KExPVFRfT1VUUFVUKSkKCmRlc2lnbi5tYXRyaXgkVmlvbF9jcmltZV9yYXRlXzFrX2xvZyA8LSBwbG06OldpdGhpbigKICBkX3BhbmVsX0xPVFQkVmlvbF9jcmltZV9yYXRlXzFrX2xvZykKCkxPVFRfdmFyaWFibGVzX29scyA8LSBMT1RUX0RGICU+JQogIGRwbHlyOjpzZWxlY3QoUlRDX0xBVywKICAgICAgICAgICAgICAgIGNvbnRhaW5zKGMoIldoaXRlIiwiQmxhY2siLCJPdGhlciIpKSwKICAgICAgICAgICAgICAgIFVuZW1wbG95bWVudF9yYXRlLAogICAgICAgICAgICAgICAgUG92ZXJ0eV9yYXRlLAogICAgICAgICAgICAgICAgUG9wdWxhdGlvbl9sb2csCiAgICAgICAgICAgICAgICBwb2xpY2VfcGVyXzEwMGtfbGFnKSAlPiUKICBjb2xuYW1lcygpICU+JQogIHN0cl9yZXBsYWNlKCJSVENfTEFXIiwgIlJUQ19MQVdUUlVFIikgIyBsb2dpY2FsIGNsYXNzIGNoYW5nZXMgdmFyaWFibGUgbmFtZSBhZnRlciBpbml0YWwgbW9kZWwKCkxPVFRfZm1sYV9vbHMgPC0gYXMuZm9ybXVsYShwYXN0ZSgiVmlvbF9jcmltZV9yYXRlXzFrX2xvZyB+IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoTE9UVF92YXJpYWJsZXNfb2xzLCBjb2xsYXBzZSA9ICIgKyAiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICkKCmxtX0xPVFQgPC0gbG0oTE9UVF9mbWxhX29scywKICAgICAgICAgICAgIGRhdGEgPSBkZXNpZ24ubWF0cml4KQoKdmlmKGxtX0xPVFQpCgp2aWZfTE9UVCA8LSB2aWYobG1fTE9UVCkKCnZpZl9MT1RUIDwtIHZpZl9MT1RUICU+JQogIGFzX3RpYmJsZSgpICU+JQogIGNiaW5kKC4sIG5hbWVzKHZpZl9MT1RUKSkgJT4lCiAgYXNfdGliYmxlKCkKICAKY29sbmFtZXModmlmX0xPVFQpIDwtIGMoIlZJRiIsICJWYXJpYWJsZSIpCgptYXhfdmlmX0xPVFQgPC0gbWF4KHZpZihsbV9MT1RUKSkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KI1RoaXMgY291bGQgYmUgdXNlZCB0byBsYWJlbCB0aGUgbWF4IFZJRiBvZiBlYWNoIGFuYWx5c2lzCgptYXhfdmlmX0RPTk9IVUUKbWF4X3ZpZl9MT1RUCmBgYAoKJCRcZnJhY3sxfXsxLVJfe2l9XnsyfX0kJAoKYGBge3J9CnZpZl9ET05PSFVFJEFuYWx5c2lzIDwtICJBbmFseXNpcyAxIgp2aWZfTE9UVCRBbmFseXNpcyA8LSAiQW5hbHlzaXMgMiIKCnZpZl9kZiA8LSByYmluZCh2aWZfRE9OT0hVRSwKICAgICAgICAgICAgICAgIHZpZl9MT1RUKQoKdmlmX3Bsb3QgPC0gdmlmX2RmICU+JQogIGdncGxvdChhZXMoeCA9IEFuYWx5c2lzLCB5ID0gVklGKSkgKwogIGdlb21faml0dGVyKHdpZHRoID0gMC4xLCBhbHBoYSA9IDAuNSwgc2l6ZSA9IDIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxMCwgY29sb3IgPSAicmVkIikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICdsb2cxMCcsCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMSwxMDAwKSkgKwogIGxhYnModGl0bGUgPSAiVmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvcnMiKSArIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKdmlmX3Bsb3QKYGBgCgojIFN5bnRoZXNpcwoKYGBge3IsIGZpZy5oZWlnaHQ9MTAsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnRpdGxlX3Bsb3RzIDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgICJNdWx0aWNvbGxpbmVhcml0eSBhbmQgaXRzIGVmZmVjdHMiLAogICAgZm9udGZhY2UgPSAnYm9sZCcsCiAgICBzaXplPTE4LAogICAgeCA9IDAsCiAgICBoanVzdCA9IDAKICApICsKICB0aGVtZSgKICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDApCiAgKQoKZm9yd2FyZCA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICAiQW5hbHlzaXMgMTogNiBkZW1vZ3JhcGhpYyB2YXJpYWJsZXNcbkFuYWx5c2lzIDI6IDM2IGRlbW9ncmFwaGljIHZhcmlhYmxlcyIsCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTAsCiAgICB4ID0gMCwKICAgIGhqdXN0ID0gMAogICkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpjb3JyX21hdF9ET05PSFVFIDwtIGdnY29ycnBsb3QoY29yX0RPTk9IVUVfZGVtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGwuY2V4ID0gNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhjLm9yZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGxpbmUuY29sb3IgPSAidHJhbnNwYXJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndoaXRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInJlZCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gVGVYKCIkXFxyaG8kIikpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShwbG90LnRpdGxlPSBlbGVtZW50X3RleHQoc2l6ZT04KSkgKwogIGxhYnModGl0bGUgPSAiQW5hbHlzaXMgMSIpIAoKY29ycl9tYXRfTE9UVCA8LSBnZ2NvcnJwbG90KGNvcl9MT1RUX2RlbSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRsLmNleCA9IDYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYy5vcmRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRsaW5lLmNvbG9yID0gInRyYW5zcGFyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoInJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3aGl0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJyZWQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IFRlWCgiJFxccmhvJCIpKSArCiAgdGhlbWVfdm9pZCgpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTgpKSArCiAgbGFicyh0aXRsZSA9ICJBbmFseXNpcyAyIikgCgpwbG90X0ExIDwtIGNvcnJfbWF0X0RPTk9IVUUKCnBsb3RfQTIgPC0gY29ycl9tYXRfTE9UVAoKcm93X0EgPC0gcGxvdF9ncmlkKHBsb3RfQTEsCiAgICAgICAgICAgICAgICAgICBwbG90X0EyLAogICAgICAgICAgICAgICAgICAgbnJvdyA9IDEpCgp0aXRsZV9BIDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgICJDb3JyZWxhdGlvbiBiZXR3ZWVuIHZhcmlhYmxlcyBjYW4gaW5kdWNlIG11bHRpY29sbGluZWFyaXR5IiwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCmxlZ2VuZF9BIDwtIGdldF9sZWdlbmQoY29ycl9tYXRfTE9UVCkKCnBsb3RfQSA8LSBwbG90X2dyaWQodGl0bGVfQSwKICAgICAgICAgICAgICAgICAgICByb3dfQSwKICAgICAgICAgICAgICAgICAgICBuY29sID0gMSwKICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLDEpKQoKZW1wdHlfZGYgPC0gY2JpbmQoYygxOjEwKSxjKDE6MTApKSAlPiUKICBhcy5kYXRhLmZyYW1lKCkKCmNvbG5hbWVzKGVtcHR5X2RmKSA8LSBjKCJYIiwgIlkiKQoKcGxvdF9CMSA8LSBnZ3Bsb3QoZW1wdHlfZGYsIGFlcyh4ID0gWCwgeSA9IFkpKSArCiAgYW5ub3RhdGUoInRleHQiLAogICAgICAgICAgIHg9NSwKICAgICAgICAgICB5PTUsCiAgICAgICAgICAgbGFiZWwgPSBUZVgoIiRWSUZfe2l9ID0gXFxmcmFjezF9ezEtUl97aX1eezJ9fSQiKSwKICAgICAgICAgICBzaXplID0gOCkgKwogIHRoZW1lX3ZvaWQoKQoKcGxvdF9CMiA8LSB2aWZfcGxvdCArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9OCkpCgpyb3dfQiA8LSBwbG90X2dyaWQocGxvdF9CMSwKICAgICAgICAgICAgICAgICAgICAgICBwbG90X0IyLAogICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSAxKQoKdGl0bGVfQiA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICAiVmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvcnMgY2FuIGJlIHVzZWQgdG8gaWRlbnRpZnkgbXVsdGljb2xsaW5lYXJpdHkgd2hlbiBwcmVzZW50IiwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RfQiA8LSBwbG90X2dyaWQodGl0bGVfQiwKICAgICAgICAgICAgICAgICAgICByb3dfQiwKICAgICAgICAgICAgICAgICAgICBuY29sID0gMSwKICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLDEpKQoKcGxvdF9DMSA8LSBjb21wYXJpbmdfYW5hbHlzZXNfcGxvdCArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKHRpdGxlID0gIkludHJvZHVjZXMgYmlhcyB0byBlc3RpbWF0ZXMiLAogICAgICAgc3VidGl0bGUgPSAiQmlhcyBpbnRyb2R1Y2VkIGNhbiBjaGFuZ2UgZGlyZWN0aW9uIG9mIGVzdGltYXRlIikKCnBsb3RfQzIgPC0gc2ltdWxhdGlvbl9wbG90ICsKICBsYWJzKHRpdGxlID0gIlJlZHVjZXMgcHJlY2lzaW9uIGluIGVzdGltYXRlcyIpCgpyb3dfQyA8LSBwbG90X2dyaWQocGxvdF9DMSwKICAgICAgICAgICAgICAgICAgICAgICBwbG90X0MyLAogICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSAxKQoKdGl0bGVfQyA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICAiTXVsdGljb2xsaW5lYXJpdHkgY2FuIGhhdmUgYSBuZWdhdGl2ZSBlZmZlY3Qgb24gc3RhdGlzdGljYWwgaW5mZXJlbmNlIiwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RfQyA8LSBwbG90X2dyaWQodGl0bGVfQywKICAgICAgICAgICAgICAgICAgICByb3dfQywKICAgICAgICAgICAgICAgICAgICBuY29sID0gMSwKICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLDEpKQoKcGxvdHMgPC0gcGxvdF9ncmlkKHBsb3RfQSwKICAgICAgICAgICAgICAgICAgIHBsb3RfQiwKICAgICAgICAgICAgICAgICAgIHBsb3RfQywKICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDEsMSwxKSkKCm1haW5wbG90IDwtIHBsb3RfZ3JpZCh0aXRsZV9wbG90cywKICAgICAgICAgICAgICAgICAgICAgICBmb3J3YXJkLAogICAgICAgICAgICAgICAgICAgICAgIHBsb3RzLAogICAgICAgICAgICAgICAgICAgICAgICNsZWdlbmRfdXcsCiAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuMDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAuMDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEpKQoKbWFpbnBsb3QKYGBgCgoKCmBgYHtyLCBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpnZ3NhdmUoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5wbG90LnBuZyIpKQpgYGAKCgoKCiMgKipEYXRhIFZpc3VhbGl6YXRpb24qKgoqKiogCgojICoqU3VtbWFyeSoqCioqKiAKCiMgKipTdWdnZXN0ZWQgSG9tZXdvcmsqKgoqKiogCgojICoqSGVscGZ1bCBMaW5rcyoqCioqKiAKCmh0dHBzOi8vcnB1YnMuY29tL3JzbGJsaXNzL2ZpeGVkX2VmZmVjdHMKCmh0dHA6Ly9rYXJ0aHVyLm9yZy8yMDE5L2ltcGxlbWVudGluZy1maXhlZC1lZmZlY3RzLXBhbmVsLW1vZGVscy1pbi1yLmh0bWwKCmh0dHBzOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzk5MjM2L2VmZmVjdHMtaW4tcGFuZWwtbW9kZWxzLWluZGl2aWR1YWwtdGltZS1vci10d293YXlzCgo=